diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2011-03-24 10:56:52 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2011-03-24 10:56:52 -0400 |
commit | 4cc4d24efce4672f9b0e7fa27963770ae602998f (patch) | |
tree | e69e7209db5500164eedb82c46ea657499b72287 /drivers/video | |
parent | b81a618dcd3ea99de292dbe624f41ca68f464376 (diff) | |
parent | 56be1416453c31d32f984328b5193489ab63ffcf (diff) |
Merge git://git.kernel.org/pub/scm/linux/kernel/git/lethal/fbdev-2.6
* git://git.kernel.org/pub/scm/linux/kernel/git/lethal/fbdev-2.6: (140 commits)
MAINTAINERS: de-orphan fbdev.
MAINTAINERS: Add file pattern for fb dt bindings.
video: Move sm501fb devicetree binding documentation to a better place.
fbcon: fix situation where fbcon gets deinitialised and can't reinit.
video, sm501: add OF binding to support SM501
video, sm501: add edid and commandline support
video, sm501: add I/O functions for use on powerpc
video: Fix EDID macros H_SYNC_WIDTH and H_SYNC_OFFSET
fbcon: Bugfix soft cursor detection in Tile Blitting
video: add missing framebuffer_release in error path
video: metronomefb: add __devexit_p around reference to metronomefb_remove
video: hecubafb: add __devexit_p around reference to hecubafb_remove
drivers:video:aty:radeon_base Fix typo occationally to occasionally
atmel_lcdfb: add fb_blank function
atmel_lcdfb: implement inverted contrast pwm
video: s3c-fb: return proper error if clk_get fails
uvesafb,vesafb: create WC or WB PAT-entries
video: ffb: fix ffb_probe error path
radeonfb: Let hwmon driver probe the "monid" I2C bus
fbdev: sh_mobile_lcdc: checking NULL instead of IS_ERR()
...
Diffstat (limited to 'drivers/video')
56 files changed, 5542 insertions, 1820 deletions
diff --git a/drivers/video/arkfb.c b/drivers/video/arkfb.c index 391ac939f011..8686429cbdf0 100644 --- a/drivers/video/arkfb.c +++ b/drivers/video/arkfb.c | |||
@@ -158,12 +158,19 @@ static void arkfb_settile(struct fb_info *info, struct fb_tilemap *map) | |||
158 | } | 158 | } |
159 | } | 159 | } |
160 | 160 | ||
161 | static void arkfb_tilecursor(struct fb_info *info, struct fb_tilecursor *cursor) | ||
162 | { | ||
163 | struct arkfb_info *par = info->par; | ||
164 | |||
165 | svga_tilecursor(par->state.vgabase, info, cursor); | ||
166 | } | ||
167 | |||
161 | static struct fb_tile_ops arkfb_tile_ops = { | 168 | static struct fb_tile_ops arkfb_tile_ops = { |
162 | .fb_settile = arkfb_settile, | 169 | .fb_settile = arkfb_settile, |
163 | .fb_tilecopy = svga_tilecopy, | 170 | .fb_tilecopy = svga_tilecopy, |
164 | .fb_tilefill = svga_tilefill, | 171 | .fb_tilefill = svga_tilefill, |
165 | .fb_tileblit = svga_tileblit, | 172 | .fb_tileblit = svga_tileblit, |
166 | .fb_tilecursor = svga_tilecursor, | 173 | .fb_tilecursor = arkfb_tilecursor, |
167 | .fb_get_tilemax = svga_get_tilemax, | 174 | .fb_get_tilemax = svga_get_tilemax, |
168 | }; | 175 | }; |
169 | 176 | ||
@@ -466,32 +473,40 @@ static unsigned short dac_regs[4] = {0x3c8, 0x3c9, 0x3c6, 0x3c7}; | |||
466 | 473 | ||
467 | static void ark_dac_read_regs(void *data, u8 *code, int count) | 474 | static void ark_dac_read_regs(void *data, u8 *code, int count) |
468 | { | 475 | { |
469 | u8 regval = vga_rseq(NULL, 0x1C); | 476 | struct fb_info *info = data; |
477 | struct arkfb_info *par; | ||
478 | u8 regval; | ||
470 | 479 | ||
480 | par = info->par; | ||
481 | regval = vga_rseq(par->state.vgabase, 0x1C); | ||
471 | while (count != 0) | 482 | while (count != 0) |
472 | { | 483 | { |
473 | vga_wseq(NULL, 0x1C, regval | (code[0] & 4 ? 0x80 : 0)); | 484 | vga_wseq(par->state.vgabase, 0x1C, regval | (code[0] & 4 ? 0x80 : 0)); |
474 | code[1] = vga_r(NULL, dac_regs[code[0] & 3]); | 485 | code[1] = vga_r(par->state.vgabase, dac_regs[code[0] & 3]); |
475 | count--; | 486 | count--; |
476 | code += 2; | 487 | code += 2; |
477 | } | 488 | } |
478 | 489 | ||
479 | vga_wseq(NULL, 0x1C, regval); | 490 | vga_wseq(par->state.vgabase, 0x1C, regval); |
480 | } | 491 | } |
481 | 492 | ||
482 | static void ark_dac_write_regs(void *data, u8 *code, int count) | 493 | static void ark_dac_write_regs(void *data, u8 *code, int count) |
483 | { | 494 | { |
484 | u8 regval = vga_rseq(NULL, 0x1C); | 495 | struct fb_info *info = data; |
496 | struct arkfb_info *par; | ||
497 | u8 regval; | ||
485 | 498 | ||
499 | par = info->par; | ||
500 | regval = vga_rseq(par->state.vgabase, 0x1C); | ||
486 | while (count != 0) | 501 | while (count != 0) |
487 | { | 502 | { |
488 | vga_wseq(NULL, 0x1C, regval | (code[0] & 4 ? 0x80 : 0)); | 503 | vga_wseq(par->state.vgabase, 0x1C, regval | (code[0] & 4 ? 0x80 : 0)); |
489 | vga_w(NULL, dac_regs[code[0] & 3], code[1]); | 504 | vga_w(par->state.vgabase, dac_regs[code[0] & 3], code[1]); |
490 | count--; | 505 | count--; |
491 | code += 2; | 506 | code += 2; |
492 | } | 507 | } |
493 | 508 | ||
494 | vga_wseq(NULL, 0x1C, regval); | 509 | vga_wseq(par->state.vgabase, 0x1C, regval); |
495 | } | 510 | } |
496 | 511 | ||
497 | 512 | ||
@@ -507,8 +522,8 @@ static void ark_set_pixclock(struct fb_info *info, u32 pixclock) | |||
507 | } | 522 | } |
508 | 523 | ||
509 | /* Set VGA misc register */ | 524 | /* Set VGA misc register */ |
510 | regval = vga_r(NULL, VGA_MIS_R); | 525 | regval = vga_r(par->state.vgabase, VGA_MIS_R); |
511 | vga_w(NULL, VGA_MIS_W, regval | VGA_MIS_ENB_PLL_LOAD); | 526 | vga_w(par->state.vgabase, VGA_MIS_W, regval | VGA_MIS_ENB_PLL_LOAD); |
512 | } | 527 | } |
513 | 528 | ||
514 | 529 | ||
@@ -520,7 +535,10 @@ static int arkfb_open(struct fb_info *info, int user) | |||
520 | 535 | ||
521 | mutex_lock(&(par->open_lock)); | 536 | mutex_lock(&(par->open_lock)); |
522 | if (par->ref_count == 0) { | 537 | if (par->ref_count == 0) { |
538 | void __iomem *vgabase = par->state.vgabase; | ||
539 | |||
523 | memset(&(par->state), 0, sizeof(struct vgastate)); | 540 | memset(&(par->state), 0, sizeof(struct vgastate)); |
541 | par->state.vgabase = vgabase; | ||
524 | par->state.flags = VGA_SAVE_MODE | VGA_SAVE_FONTS | VGA_SAVE_CMAP; | 542 | par->state.flags = VGA_SAVE_MODE | VGA_SAVE_FONTS | VGA_SAVE_CMAP; |
525 | par->state.num_crtc = 0x60; | 543 | par->state.num_crtc = 0x60; |
526 | par->state.num_seq = 0x30; | 544 | par->state.num_seq = 0x30; |
@@ -646,50 +664,50 @@ static int arkfb_set_par(struct fb_info *info) | |||
646 | info->var.activate = FB_ACTIVATE_NOW; | 664 | info->var.activate = FB_ACTIVATE_NOW; |
647 | 665 | ||
648 | /* Unlock registers */ | 666 | /* Unlock registers */ |
649 | svga_wcrt_mask(0x11, 0x00, 0x80); | 667 | svga_wcrt_mask(par->state.vgabase, 0x11, 0x00, 0x80); |
650 | 668 | ||
651 | /* Blank screen and turn off sync */ | 669 | /* Blank screen and turn off sync */ |
652 | svga_wseq_mask(0x01, 0x20, 0x20); | 670 | svga_wseq_mask(par->state.vgabase, 0x01, 0x20, 0x20); |
653 | svga_wcrt_mask(0x17, 0x00, 0x80); | 671 | svga_wcrt_mask(par->state.vgabase, 0x17, 0x00, 0x80); |
654 | 672 | ||
655 | /* Set default values */ | 673 | /* Set default values */ |
656 | svga_set_default_gfx_regs(); | 674 | svga_set_default_gfx_regs(par->state.vgabase); |
657 | svga_set_default_atc_regs(); | 675 | svga_set_default_atc_regs(par->state.vgabase); |
658 | svga_set_default_seq_regs(); | 676 | svga_set_default_seq_regs(par->state.vgabase); |
659 | svga_set_default_crt_regs(); | 677 | svga_set_default_crt_regs(par->state.vgabase); |
660 | svga_wcrt_multi(ark_line_compare_regs, 0xFFFFFFFF); | 678 | svga_wcrt_multi(par->state.vgabase, ark_line_compare_regs, 0xFFFFFFFF); |
661 | svga_wcrt_multi(ark_start_address_regs, 0); | 679 | svga_wcrt_multi(par->state.vgabase, ark_start_address_regs, 0); |
662 | 680 | ||
663 | /* ARK specific initialization */ | 681 | /* ARK specific initialization */ |
664 | svga_wseq_mask(0x10, 0x1F, 0x1F); /* enable linear framebuffer and full memory access */ | 682 | svga_wseq_mask(par->state.vgabase, 0x10, 0x1F, 0x1F); /* enable linear framebuffer and full memory access */ |
665 | svga_wseq_mask(0x12, 0x03, 0x03); /* 4 MB linear framebuffer size */ | 683 | svga_wseq_mask(par->state.vgabase, 0x12, 0x03, 0x03); /* 4 MB linear framebuffer size */ |
666 | 684 | ||
667 | vga_wseq(NULL, 0x13, info->fix.smem_start >> 16); | 685 | vga_wseq(par->state.vgabase, 0x13, info->fix.smem_start >> 16); |
668 | vga_wseq(NULL, 0x14, info->fix.smem_start >> 24); | 686 | vga_wseq(par->state.vgabase, 0x14, info->fix.smem_start >> 24); |
669 | vga_wseq(NULL, 0x15, 0); | 687 | vga_wseq(par->state.vgabase, 0x15, 0); |
670 | vga_wseq(NULL, 0x16, 0); | 688 | vga_wseq(par->state.vgabase, 0x16, 0); |
671 | 689 | ||
672 | /* Set the FIFO threshold register */ | 690 | /* Set the FIFO threshold register */ |
673 | /* It is fascinating way to store 5-bit value in 8-bit register */ | 691 | /* It is fascinating way to store 5-bit value in 8-bit register */ |
674 | regval = 0x10 | ((threshold & 0x0E) >> 1) | (threshold & 0x01) << 7 | (threshold & 0x10) << 1; | 692 | regval = 0x10 | ((threshold & 0x0E) >> 1) | (threshold & 0x01) << 7 | (threshold & 0x10) << 1; |
675 | vga_wseq(NULL, 0x18, regval); | 693 | vga_wseq(par->state.vgabase, 0x18, regval); |
676 | 694 | ||
677 | /* Set the offset register */ | 695 | /* Set the offset register */ |
678 | pr_debug("fb%d: offset register : %d\n", info->node, offset_value); | 696 | pr_debug("fb%d: offset register : %d\n", info->node, offset_value); |
679 | svga_wcrt_multi(ark_offset_regs, offset_value); | 697 | svga_wcrt_multi(par->state.vgabase, ark_offset_regs, offset_value); |
680 | 698 | ||
681 | /* fix for hi-res textmode */ | 699 | /* fix for hi-res textmode */ |
682 | svga_wcrt_mask(0x40, 0x08, 0x08); | 700 | svga_wcrt_mask(par->state.vgabase, 0x40, 0x08, 0x08); |
683 | 701 | ||
684 | if (info->var.vmode & FB_VMODE_DOUBLE) | 702 | if (info->var.vmode & FB_VMODE_DOUBLE) |
685 | svga_wcrt_mask(0x09, 0x80, 0x80); | 703 | svga_wcrt_mask(par->state.vgabase, 0x09, 0x80, 0x80); |
686 | else | 704 | else |
687 | svga_wcrt_mask(0x09, 0x00, 0x80); | 705 | svga_wcrt_mask(par->state.vgabase, 0x09, 0x00, 0x80); |
688 | 706 | ||
689 | if (info->var.vmode & FB_VMODE_INTERLACED) | 707 | if (info->var.vmode & FB_VMODE_INTERLACED) |
690 | svga_wcrt_mask(0x44, 0x04, 0x04); | 708 | svga_wcrt_mask(par->state.vgabase, 0x44, 0x04, 0x04); |
691 | else | 709 | else |
692 | svga_wcrt_mask(0x44, 0x00, 0x04); | 710 | svga_wcrt_mask(par->state.vgabase, 0x44, 0x00, 0x04); |
693 | 711 | ||
694 | hmul = 1; | 712 | hmul = 1; |
695 | hdiv = 1; | 713 | hdiv = 1; |
@@ -699,40 +717,40 @@ static int arkfb_set_par(struct fb_info *info) | |||
699 | switch (mode) { | 717 | switch (mode) { |
700 | case 0: | 718 | case 0: |
701 | pr_debug("fb%d: text mode\n", info->node); | 719 | pr_debug("fb%d: text mode\n", info->node); |
702 | svga_set_textmode_vga_regs(); | 720 | svga_set_textmode_vga_regs(par->state.vgabase); |
703 | 721 | ||
704 | vga_wseq(NULL, 0x11, 0x10); /* basic VGA mode */ | 722 | vga_wseq(par->state.vgabase, 0x11, 0x10); /* basic VGA mode */ |
705 | svga_wcrt_mask(0x46, 0x00, 0x04); /* 8bit pixel path */ | 723 | svga_wcrt_mask(par->state.vgabase, 0x46, 0x00, 0x04); /* 8bit pixel path */ |
706 | dac_set_mode(par->dac, DAC_PSEUDO8_8); | 724 | dac_set_mode(par->dac, DAC_PSEUDO8_8); |
707 | 725 | ||
708 | break; | 726 | break; |
709 | case 1: | 727 | case 1: |
710 | pr_debug("fb%d: 4 bit pseudocolor\n", info->node); | 728 | pr_debug("fb%d: 4 bit pseudocolor\n", info->node); |
711 | vga_wgfx(NULL, VGA_GFX_MODE, 0x40); | 729 | vga_wgfx(par->state.vgabase, VGA_GFX_MODE, 0x40); |
712 | 730 | ||
713 | vga_wseq(NULL, 0x11, 0x10); /* basic VGA mode */ | 731 | vga_wseq(par->state.vgabase, 0x11, 0x10); /* basic VGA mode */ |
714 | svga_wcrt_mask(0x46, 0x00, 0x04); /* 8bit pixel path */ | 732 | svga_wcrt_mask(par->state.vgabase, 0x46, 0x00, 0x04); /* 8bit pixel path */ |
715 | dac_set_mode(par->dac, DAC_PSEUDO8_8); | 733 | dac_set_mode(par->dac, DAC_PSEUDO8_8); |
716 | break; | 734 | break; |
717 | case 2: | 735 | case 2: |
718 | pr_debug("fb%d: 4 bit pseudocolor, planar\n", info->node); | 736 | pr_debug("fb%d: 4 bit pseudocolor, planar\n", info->node); |
719 | 737 | ||
720 | vga_wseq(NULL, 0x11, 0x10); /* basic VGA mode */ | 738 | vga_wseq(par->state.vgabase, 0x11, 0x10); /* basic VGA mode */ |
721 | svga_wcrt_mask(0x46, 0x00, 0x04); /* 8bit pixel path */ | 739 | svga_wcrt_mask(par->state.vgabase, 0x46, 0x00, 0x04); /* 8bit pixel path */ |
722 | dac_set_mode(par->dac, DAC_PSEUDO8_8); | 740 | dac_set_mode(par->dac, DAC_PSEUDO8_8); |
723 | break; | 741 | break; |
724 | case 3: | 742 | case 3: |
725 | pr_debug("fb%d: 8 bit pseudocolor\n", info->node); | 743 | pr_debug("fb%d: 8 bit pseudocolor\n", info->node); |
726 | 744 | ||
727 | vga_wseq(NULL, 0x11, 0x16); /* 8bpp accel mode */ | 745 | vga_wseq(par->state.vgabase, 0x11, 0x16); /* 8bpp accel mode */ |
728 | 746 | ||
729 | if (info->var.pixclock > 20000) { | 747 | if (info->var.pixclock > 20000) { |
730 | pr_debug("fb%d: not using multiplex\n", info->node); | 748 | pr_debug("fb%d: not using multiplex\n", info->node); |
731 | svga_wcrt_mask(0x46, 0x00, 0x04); /* 8bit pixel path */ | 749 | svga_wcrt_mask(par->state.vgabase, 0x46, 0x00, 0x04); /* 8bit pixel path */ |
732 | dac_set_mode(par->dac, DAC_PSEUDO8_8); | 750 | dac_set_mode(par->dac, DAC_PSEUDO8_8); |
733 | } else { | 751 | } else { |
734 | pr_debug("fb%d: using multiplex\n", info->node); | 752 | pr_debug("fb%d: using multiplex\n", info->node); |
735 | svga_wcrt_mask(0x46, 0x04, 0x04); /* 16bit pixel path */ | 753 | svga_wcrt_mask(par->state.vgabase, 0x46, 0x04, 0x04); /* 16bit pixel path */ |
736 | dac_set_mode(par->dac, DAC_PSEUDO8_16); | 754 | dac_set_mode(par->dac, DAC_PSEUDO8_16); |
737 | hdiv = 2; | 755 | hdiv = 2; |
738 | } | 756 | } |
@@ -740,22 +758,22 @@ static int arkfb_set_par(struct fb_info *info) | |||
740 | case 4: | 758 | case 4: |
741 | pr_debug("fb%d: 5/5/5 truecolor\n", info->node); | 759 | pr_debug("fb%d: 5/5/5 truecolor\n", info->node); |
742 | 760 | ||
743 | vga_wseq(NULL, 0x11, 0x1A); /* 16bpp accel mode */ | 761 | vga_wseq(par->state.vgabase, 0x11, 0x1A); /* 16bpp accel mode */ |
744 | svga_wcrt_mask(0x46, 0x04, 0x04); /* 16bit pixel path */ | 762 | svga_wcrt_mask(par->state.vgabase, 0x46, 0x04, 0x04); /* 16bit pixel path */ |
745 | dac_set_mode(par->dac, DAC_RGB1555_16); | 763 | dac_set_mode(par->dac, DAC_RGB1555_16); |
746 | break; | 764 | break; |
747 | case 5: | 765 | case 5: |
748 | pr_debug("fb%d: 5/6/5 truecolor\n", info->node); | 766 | pr_debug("fb%d: 5/6/5 truecolor\n", info->node); |
749 | 767 | ||
750 | vga_wseq(NULL, 0x11, 0x1A); /* 16bpp accel mode */ | 768 | vga_wseq(par->state.vgabase, 0x11, 0x1A); /* 16bpp accel mode */ |
751 | svga_wcrt_mask(0x46, 0x04, 0x04); /* 16bit pixel path */ | 769 | svga_wcrt_mask(par->state.vgabase, 0x46, 0x04, 0x04); /* 16bit pixel path */ |
752 | dac_set_mode(par->dac, DAC_RGB0565_16); | 770 | dac_set_mode(par->dac, DAC_RGB0565_16); |
753 | break; | 771 | break; |
754 | case 6: | 772 | case 6: |
755 | pr_debug("fb%d: 8/8/8 truecolor\n", info->node); | 773 | pr_debug("fb%d: 8/8/8 truecolor\n", info->node); |
756 | 774 | ||
757 | vga_wseq(NULL, 0x11, 0x16); /* 8bpp accel mode ??? */ | 775 | vga_wseq(par->state.vgabase, 0x11, 0x16); /* 8bpp accel mode ??? */ |
758 | svga_wcrt_mask(0x46, 0x04, 0x04); /* 16bit pixel path */ | 776 | svga_wcrt_mask(par->state.vgabase, 0x46, 0x04, 0x04); /* 16bit pixel path */ |
759 | dac_set_mode(par->dac, DAC_RGB0888_16); | 777 | dac_set_mode(par->dac, DAC_RGB0888_16); |
760 | hmul = 3; | 778 | hmul = 3; |
761 | hdiv = 2; | 779 | hdiv = 2; |
@@ -763,8 +781,8 @@ static int arkfb_set_par(struct fb_info *info) | |||
763 | case 7: | 781 | case 7: |
764 | pr_debug("fb%d: 8/8/8/8 truecolor\n", info->node); | 782 | pr_debug("fb%d: 8/8/8/8 truecolor\n", info->node); |
765 | 783 | ||
766 | vga_wseq(NULL, 0x11, 0x1E); /* 32bpp accel mode */ | 784 | vga_wseq(par->state.vgabase, 0x11, 0x1E); /* 32bpp accel mode */ |
767 | svga_wcrt_mask(0x46, 0x04, 0x04); /* 16bit pixel path */ | 785 | svga_wcrt_mask(par->state.vgabase, 0x46, 0x04, 0x04); /* 16bit pixel path */ |
768 | dac_set_mode(par->dac, DAC_RGB8888_16); | 786 | dac_set_mode(par->dac, DAC_RGB8888_16); |
769 | hmul = 2; | 787 | hmul = 2; |
770 | break; | 788 | break; |
@@ -774,7 +792,7 @@ static int arkfb_set_par(struct fb_info *info) | |||
774 | } | 792 | } |
775 | 793 | ||
776 | ark_set_pixclock(info, (hdiv * info->var.pixclock) / hmul); | 794 | ark_set_pixclock(info, (hdiv * info->var.pixclock) / hmul); |
777 | svga_set_timings(&ark_timing_regs, &(info->var), hmul, hdiv, | 795 | svga_set_timings(par->state.vgabase, &ark_timing_regs, &(info->var), hmul, hdiv, |
778 | (info->var.vmode & FB_VMODE_DOUBLE) ? 2 : 1, | 796 | (info->var.vmode & FB_VMODE_DOUBLE) ? 2 : 1, |
779 | (info->var.vmode & FB_VMODE_INTERLACED) ? 2 : 1, | 797 | (info->var.vmode & FB_VMODE_INTERLACED) ? 2 : 1, |
780 | hmul, info->node); | 798 | hmul, info->node); |
@@ -782,12 +800,12 @@ static int arkfb_set_par(struct fb_info *info) | |||
782 | /* Set interlaced mode start/end register */ | 800 | /* Set interlaced mode start/end register */ |
783 | value = info->var.xres + info->var.left_margin + info->var.right_margin + info->var.hsync_len; | 801 | value = info->var.xres + info->var.left_margin + info->var.right_margin + info->var.hsync_len; |
784 | value = ((value * hmul / hdiv) / 8) - 5; | 802 | value = ((value * hmul / hdiv) / 8) - 5; |
785 | vga_wcrt(NULL, 0x42, (value + 1) / 2); | 803 | vga_wcrt(par->state.vgabase, 0x42, (value + 1) / 2); |
786 | 804 | ||
787 | memset_io(info->screen_base, 0x00, screen_size); | 805 | memset_io(info->screen_base, 0x00, screen_size); |
788 | /* Device and screen back on */ | 806 | /* Device and screen back on */ |
789 | svga_wcrt_mask(0x17, 0x80, 0x80); | 807 | svga_wcrt_mask(par->state.vgabase, 0x17, 0x80, 0x80); |
790 | svga_wseq_mask(0x01, 0x00, 0x20); | 808 | svga_wseq_mask(par->state.vgabase, 0x01, 0x00, 0x20); |
791 | 809 | ||
792 | return 0; | 810 | return 0; |
793 | } | 811 | } |
@@ -857,23 +875,25 @@ static int arkfb_setcolreg(u_int regno, u_int red, u_int green, u_int blue, | |||
857 | 875 | ||
858 | static int arkfb_blank(int blank_mode, struct fb_info *info) | 876 | static int arkfb_blank(int blank_mode, struct fb_info *info) |
859 | { | 877 | { |
878 | struct arkfb_info *par = info->par; | ||
879 | |||
860 | switch (blank_mode) { | 880 | switch (blank_mode) { |
861 | case FB_BLANK_UNBLANK: | 881 | case FB_BLANK_UNBLANK: |
862 | pr_debug("fb%d: unblank\n", info->node); | 882 | pr_debug("fb%d: unblank\n", info->node); |
863 | svga_wseq_mask(0x01, 0x00, 0x20); | 883 | svga_wseq_mask(par->state.vgabase, 0x01, 0x00, 0x20); |
864 | svga_wcrt_mask(0x17, 0x80, 0x80); | 884 | svga_wcrt_mask(par->state.vgabase, 0x17, 0x80, 0x80); |
865 | break; | 885 | break; |
866 | case FB_BLANK_NORMAL: | 886 | case FB_BLANK_NORMAL: |
867 | pr_debug("fb%d: blank\n", info->node); | 887 | pr_debug("fb%d: blank\n", info->node); |
868 | svga_wseq_mask(0x01, 0x20, 0x20); | 888 | svga_wseq_mask(par->state.vgabase, 0x01, 0x20, 0x20); |
869 | svga_wcrt_mask(0x17, 0x80, 0x80); | 889 | svga_wcrt_mask(par->state.vgabase, 0x17, 0x80, 0x80); |
870 | break; | 890 | break; |
871 | case FB_BLANK_POWERDOWN: | 891 | case FB_BLANK_POWERDOWN: |
872 | case FB_BLANK_HSYNC_SUSPEND: | 892 | case FB_BLANK_HSYNC_SUSPEND: |
873 | case FB_BLANK_VSYNC_SUSPEND: | 893 | case FB_BLANK_VSYNC_SUSPEND: |
874 | pr_debug("fb%d: sync down\n", info->node); | 894 | pr_debug("fb%d: sync down\n", info->node); |
875 | svga_wseq_mask(0x01, 0x20, 0x20); | 895 | svga_wseq_mask(par->state.vgabase, 0x01, 0x20, 0x20); |
876 | svga_wcrt_mask(0x17, 0x00, 0x80); | 896 | svga_wcrt_mask(par->state.vgabase, 0x17, 0x00, 0x80); |
877 | break; | 897 | break; |
878 | } | 898 | } |
879 | return 0; | 899 | return 0; |
@@ -884,6 +904,7 @@ static int arkfb_blank(int blank_mode, struct fb_info *info) | |||
884 | 904 | ||
885 | static int arkfb_pan_display(struct fb_var_screeninfo *var, struct fb_info *info) | 905 | static int arkfb_pan_display(struct fb_var_screeninfo *var, struct fb_info *info) |
886 | { | 906 | { |
907 | struct arkfb_info *par = info->par; | ||
887 | unsigned int offset; | 908 | unsigned int offset; |
888 | 909 | ||
889 | /* Calculate the offset */ | 910 | /* Calculate the offset */ |
@@ -897,7 +918,7 @@ static int arkfb_pan_display(struct fb_var_screeninfo *var, struct fb_info *info | |||
897 | } | 918 | } |
898 | 919 | ||
899 | /* Set the offset */ | 920 | /* Set the offset */ |
900 | svga_wcrt_multi(ark_start_address_regs, offset); | 921 | svga_wcrt_multi(par->state.vgabase, ark_start_address_regs, offset); |
901 | 922 | ||
902 | return 0; | 923 | return 0; |
903 | } | 924 | } |
@@ -930,6 +951,8 @@ static struct fb_ops arkfb_ops = { | |||
930 | /* PCI probe */ | 951 | /* PCI probe */ |
931 | static int __devinit ark_pci_probe(struct pci_dev *dev, const struct pci_device_id *id) | 952 | static int __devinit ark_pci_probe(struct pci_dev *dev, const struct pci_device_id *id) |
932 | { | 953 | { |
954 | struct pci_bus_region bus_reg; | ||
955 | struct resource vga_res; | ||
933 | struct fb_info *info; | 956 | struct fb_info *info; |
934 | struct arkfb_info *par; | 957 | struct arkfb_info *par; |
935 | int rc; | 958 | int rc; |
@@ -985,8 +1008,17 @@ static int __devinit ark_pci_probe(struct pci_dev *dev, const struct pci_device_ | |||
985 | goto err_iomap; | 1008 | goto err_iomap; |
986 | } | 1009 | } |
987 | 1010 | ||
1011 | bus_reg.start = 0; | ||
1012 | bus_reg.end = 64 * 1024; | ||
1013 | |||
1014 | vga_res.flags = IORESOURCE_IO; | ||
1015 | |||
1016 | pcibios_bus_to_resource(dev, &vga_res, &bus_reg); | ||
1017 | |||
1018 | par->state.vgabase = (void __iomem *) vga_res.start; | ||
1019 | |||
988 | /* FIXME get memsize */ | 1020 | /* FIXME get memsize */ |
989 | regval = vga_rseq(NULL, 0x10); | 1021 | regval = vga_rseq(par->state.vgabase, 0x10); |
990 | info->screen_size = (1 << (regval >> 6)) << 20; | 1022 | info->screen_size = (1 << (regval >> 6)) << 20; |
991 | info->fix.smem_len = info->screen_size; | 1023 | info->fix.smem_len = info->screen_size; |
992 | 1024 | ||
diff --git a/drivers/video/atmel_lcdfb.c b/drivers/video/atmel_lcdfb.c index 4b4e8dadd6b2..ccecf9974587 100644 --- a/drivers/video/atmel_lcdfb.c +++ b/drivers/video/atmel_lcdfb.c | |||
@@ -68,7 +68,7 @@ static void atmel_lcdfb_update_dma2d(struct atmel_lcdfb_info *sinfo, | |||
68 | } | 68 | } |
69 | #endif | 69 | #endif |
70 | 70 | ||
71 | static const u32 contrast_ctr = ATMEL_LCDC_PS_DIV8 | 71 | static u32 contrast_ctr = ATMEL_LCDC_PS_DIV8 |
72 | | ATMEL_LCDC_POL_POSITIVE | 72 | | ATMEL_LCDC_POL_POSITIVE |
73 | | ATMEL_LCDC_ENA_PWMENABLE; | 73 | | ATMEL_LCDC_ENA_PWMENABLE; |
74 | 74 | ||
@@ -164,6 +164,10 @@ static void exit_backlight(struct atmel_lcdfb_info *sinfo) | |||
164 | 164 | ||
165 | static void init_contrast(struct atmel_lcdfb_info *sinfo) | 165 | static void init_contrast(struct atmel_lcdfb_info *sinfo) |
166 | { | 166 | { |
167 | /* contrast pwm can be 'inverted' */ | ||
168 | if (sinfo->lcdcon_pol_negative) | ||
169 | contrast_ctr &= ~(ATMEL_LCDC_POL_POSITIVE); | ||
170 | |||
167 | /* have some default contrast/backlight settings */ | 171 | /* have some default contrast/backlight settings */ |
168 | lcdc_writel(sinfo, ATMEL_LCDC_CONTRAST_CTR, contrast_ctr); | 172 | lcdc_writel(sinfo, ATMEL_LCDC_CONTRAST_CTR, contrast_ctr); |
169 | lcdc_writel(sinfo, ATMEL_LCDC_CONTRAST_VAL, ATMEL_LCDC_CVAL_DEFAULT); | 173 | lcdc_writel(sinfo, ATMEL_LCDC_CONTRAST_VAL, ATMEL_LCDC_CVAL_DEFAULT); |
@@ -711,11 +715,35 @@ static int atmel_lcdfb_pan_display(struct fb_var_screeninfo *var, | |||
711 | return 0; | 715 | return 0; |
712 | } | 716 | } |
713 | 717 | ||
718 | static int atmel_lcdfb_blank(int blank_mode, struct fb_info *info) | ||
719 | { | ||
720 | struct atmel_lcdfb_info *sinfo = info->par; | ||
721 | |||
722 | switch (blank_mode) { | ||
723 | case FB_BLANK_UNBLANK: | ||
724 | case FB_BLANK_NORMAL: | ||
725 | atmel_lcdfb_start(sinfo); | ||
726 | break; | ||
727 | case FB_BLANK_VSYNC_SUSPEND: | ||
728 | case FB_BLANK_HSYNC_SUSPEND: | ||
729 | break; | ||
730 | case FB_BLANK_POWERDOWN: | ||
731 | atmel_lcdfb_stop(sinfo); | ||
732 | break; | ||
733 | default: | ||
734 | return -EINVAL; | ||
735 | } | ||
736 | |||
737 | /* let fbcon do a soft blank for us */ | ||
738 | return ((blank_mode == FB_BLANK_NORMAL) ? 1 : 0); | ||
739 | } | ||
740 | |||
714 | static struct fb_ops atmel_lcdfb_ops = { | 741 | static struct fb_ops atmel_lcdfb_ops = { |
715 | .owner = THIS_MODULE, | 742 | .owner = THIS_MODULE, |
716 | .fb_check_var = atmel_lcdfb_check_var, | 743 | .fb_check_var = atmel_lcdfb_check_var, |
717 | .fb_set_par = atmel_lcdfb_set_par, | 744 | .fb_set_par = atmel_lcdfb_set_par, |
718 | .fb_setcolreg = atmel_lcdfb_setcolreg, | 745 | .fb_setcolreg = atmel_lcdfb_setcolreg, |
746 | .fb_blank = atmel_lcdfb_blank, | ||
719 | .fb_pan_display = atmel_lcdfb_pan_display, | 747 | .fb_pan_display = atmel_lcdfb_pan_display, |
720 | .fb_fillrect = cfb_fillrect, | 748 | .fb_fillrect = cfb_fillrect, |
721 | .fb_copyarea = cfb_copyarea, | 749 | .fb_copyarea = cfb_copyarea, |
@@ -817,6 +845,7 @@ static int __init atmel_lcdfb_probe(struct platform_device *pdev) | |||
817 | sinfo->guard_time = pdata_sinfo->guard_time; | 845 | sinfo->guard_time = pdata_sinfo->guard_time; |
818 | sinfo->smem_len = pdata_sinfo->smem_len; | 846 | sinfo->smem_len = pdata_sinfo->smem_len; |
819 | sinfo->lcdcon_is_backlight = pdata_sinfo->lcdcon_is_backlight; | 847 | sinfo->lcdcon_is_backlight = pdata_sinfo->lcdcon_is_backlight; |
848 | sinfo->lcdcon_pol_negative = pdata_sinfo->lcdcon_pol_negative; | ||
820 | sinfo->lcd_wiring_mode = pdata_sinfo->lcd_wiring_mode; | 849 | sinfo->lcd_wiring_mode = pdata_sinfo->lcd_wiring_mode; |
821 | } else { | 850 | } else { |
822 | dev_err(dev, "cannot get default configuration\n"); | 851 | dev_err(dev, "cannot get default configuration\n"); |
diff --git a/drivers/video/aty/radeon_base.c b/drivers/video/aty/radeon_base.c index 3c1e13ed1cba..32f8cf6200a7 100644 --- a/drivers/video/aty/radeon_base.c +++ b/drivers/video/aty/radeon_base.c | |||
@@ -1248,7 +1248,7 @@ static void radeon_write_pll_regs(struct radeonfb_info *rinfo, struct radeon_reg | |||
1248 | 1248 | ||
1249 | /* Workaround from XFree */ | 1249 | /* Workaround from XFree */ |
1250 | if (rinfo->is_mobility) { | 1250 | if (rinfo->is_mobility) { |
1251 | /* A temporal workaround for the occational blanking on certain laptop | 1251 | /* A temporal workaround for the occasional blanking on certain laptop |
1252 | * panels. This appears to related to the PLL divider registers | 1252 | * panels. This appears to related to the PLL divider registers |
1253 | * (fail to lock?). It occurs even when all dividers are the same | 1253 | * (fail to lock?). It occurs even when all dividers are the same |
1254 | * with their old settings. In this case we really don't need to | 1254 | * with their old settings. In this case we really don't need to |
diff --git a/drivers/video/aty/radeon_i2c.c b/drivers/video/aty/radeon_i2c.c index 78d1f4cd1fe0..ab1d0fd76316 100644 --- a/drivers/video/aty/radeon_i2c.c +++ b/drivers/video/aty/radeon_i2c.c | |||
@@ -100,6 +100,9 @@ void radeon_create_i2c_busses(struct radeonfb_info *rinfo) | |||
100 | { | 100 | { |
101 | rinfo->i2c[0].rinfo = rinfo; | 101 | rinfo->i2c[0].rinfo = rinfo; |
102 | rinfo->i2c[0].ddc_reg = GPIO_MONID; | 102 | rinfo->i2c[0].ddc_reg = GPIO_MONID; |
103 | #ifndef CONFIG_PPC | ||
104 | rinfo->i2c[0].adapter.class = I2C_CLASS_HWMON; | ||
105 | #endif | ||
103 | radeon_setup_i2c_bus(&rinfo->i2c[0], "monid"); | 106 | radeon_setup_i2c_bus(&rinfo->i2c[0], "monid"); |
104 | 107 | ||
105 | rinfo->i2c[1].rinfo = rinfo; | 108 | rinfo->i2c[1].rinfo = rinfo; |
diff --git a/drivers/video/cg14.c b/drivers/video/cg14.c index e2c85b0db632..f18895006627 100644 --- a/drivers/video/cg14.c +++ b/drivers/video/cg14.c | |||
@@ -565,6 +565,7 @@ out_dealloc_cmap: | |||
565 | 565 | ||
566 | out_unmap_regs: | 566 | out_unmap_regs: |
567 | cg14_unmap_regs(op, info, par); | 567 | cg14_unmap_regs(op, info, par); |
568 | framebuffer_release(info); | ||
568 | 569 | ||
569 | out_err: | 570 | out_err: |
570 | return err; | 571 | return err; |
diff --git a/drivers/video/cg6.c b/drivers/video/cg6.c index 4ffad90bde42..179e96cdb323 100644 --- a/drivers/video/cg6.c +++ b/drivers/video/cg6.c | |||
@@ -821,6 +821,7 @@ out_dealloc_cmap: | |||
821 | 821 | ||
822 | out_unmap_regs: | 822 | out_unmap_regs: |
823 | cg6_unmap_regs(op, info, par); | 823 | cg6_unmap_regs(op, info, par); |
824 | framebuffer_release(info); | ||
824 | 825 | ||
825 | out_err: | 826 | out_err: |
826 | return err; | 827 | return err; |
diff --git a/drivers/video/console/fbcon.c b/drivers/video/console/fbcon.c index 9c092b8d64e6..c58393402da2 100644 --- a/drivers/video/console/fbcon.c +++ b/drivers/video/console/fbcon.c | |||
@@ -823,10 +823,10 @@ static int set_con2fb_map(int unit, int newidx, int user) | |||
823 | if (oldidx == newidx) | 823 | if (oldidx == newidx) |
824 | return 0; | 824 | return 0; |
825 | 825 | ||
826 | if (!info || fbcon_has_exited) | 826 | if (!info) |
827 | return -EINVAL; | 827 | return -EINVAL; |
828 | 828 | ||
829 | if (!err && !search_for_mapped_con()) { | 829 | if (!search_for_mapped_con() || !con_is_bound(&fb_con)) { |
830 | info_idx = newidx; | 830 | info_idx = newidx; |
831 | return fbcon_takeover(0); | 831 | return fbcon_takeover(0); |
832 | } | 832 | } |
diff --git a/drivers/video/console/tileblit.c b/drivers/video/console/tileblit.c index 0056a41e5c35..15e8e1a89c45 100644 --- a/drivers/video/console/tileblit.c +++ b/drivers/video/console/tileblit.c | |||
@@ -83,7 +83,7 @@ static void tile_cursor(struct vc_data *vc, struct fb_info *info, int mode, | |||
83 | int softback_lines, int fg, int bg) | 83 | int softback_lines, int fg, int bg) |
84 | { | 84 | { |
85 | struct fb_tilecursor cursor; | 85 | struct fb_tilecursor cursor; |
86 | int use_sw = (vc->vc_cursor_type & 0x01); | 86 | int use_sw = (vc->vc_cursor_type & 0x10); |
87 | 87 | ||
88 | cursor.sx = vc->vc_x; | 88 | cursor.sx = vc->vc_x; |
89 | cursor.sy = vc->vc_y; | 89 | cursor.sy = vc->vc_y; |
diff --git a/drivers/video/edid.h b/drivers/video/edid.h index bd89fb3be8c2..d03a232d90b2 100644 --- a/drivers/video/edid.h +++ b/drivers/video/edid.h | |||
@@ -101,8 +101,8 @@ | |||
101 | #define V_SYNC_WIDTH COMBINE_HI_4LO( V_SYNC_WIDTH_HI, V_SYNC_WIDTH_LO ) | 101 | #define V_SYNC_WIDTH COMBINE_HI_4LO( V_SYNC_WIDTH_HI, V_SYNC_WIDTH_LO ) |
102 | #define V_SYNC_OFFSET COMBINE_HI_4LO( V_SYNC_OFFSET_HI, V_SYNC_OFFSET_LO ) | 102 | #define V_SYNC_OFFSET COMBINE_HI_4LO( V_SYNC_OFFSET_HI, V_SYNC_OFFSET_LO ) |
103 | 103 | ||
104 | #define H_SYNC_WIDTH COMBINE_HI_4LO( H_SYNC_WIDTH_HI, H_SYNC_WIDTH_LO ) | 104 | #define H_SYNC_WIDTH COMBINE_HI_8LO( H_SYNC_WIDTH_HI, H_SYNC_WIDTH_LO ) |
105 | #define H_SYNC_OFFSET COMBINE_HI_4LO( H_SYNC_OFFSET_HI, H_SYNC_OFFSET_LO ) | 105 | #define H_SYNC_OFFSET COMBINE_HI_8LO( H_SYNC_OFFSET_HI, H_SYNC_OFFSET_LO ) |
106 | 106 | ||
107 | #define H_SIZE_LO (unsigned)block[ 12 ] | 107 | #define H_SIZE_LO (unsigned)block[ 12 ] |
108 | #define V_SIZE_LO (unsigned)block[ 13 ] | 108 | #define V_SIZE_LO (unsigned)block[ 13 ] |
diff --git a/drivers/video/ffb.c b/drivers/video/ffb.c index 910c5e6f6702..14102a3f70f5 100644 --- a/drivers/video/ffb.c +++ b/drivers/video/ffb.c | |||
@@ -1010,7 +1010,7 @@ out_dealloc_cmap: | |||
1010 | fb_dealloc_cmap(&info->cmap); | 1010 | fb_dealloc_cmap(&info->cmap); |
1011 | 1011 | ||
1012 | out_unmap_dac: | 1012 | out_unmap_dac: |
1013 | of_iounmap(&op->resource[2], par->fbc, sizeof(struct ffb_fbc)); | 1013 | of_iounmap(&op->resource[1], par->dac, sizeof(struct ffb_dac)); |
1014 | 1014 | ||
1015 | out_unmap_fbc: | 1015 | out_unmap_fbc: |
1016 | of_iounmap(&op->resource[2], par->fbc, sizeof(struct ffb_fbc)); | 1016 | of_iounmap(&op->resource[2], par->fbc, sizeof(struct ffb_fbc)); |
diff --git a/drivers/video/hecubafb.c b/drivers/video/hecubafb.c index c77bcc6ab463..1b94643ecbcf 100644 --- a/drivers/video/hecubafb.c +++ b/drivers/video/hecubafb.c | |||
@@ -299,7 +299,7 @@ static int __devexit hecubafb_remove(struct platform_device *dev) | |||
299 | 299 | ||
300 | static struct platform_driver hecubafb_driver = { | 300 | static struct platform_driver hecubafb_driver = { |
301 | .probe = hecubafb_probe, | 301 | .probe = hecubafb_probe, |
302 | .remove = hecubafb_remove, | 302 | .remove = __devexit_p(hecubafb_remove), |
303 | .driver = { | 303 | .driver = { |
304 | .owner = THIS_MODULE, | 304 | .owner = THIS_MODULE, |
305 | .name = "hecubafb", | 305 | .name = "hecubafb", |
diff --git a/drivers/video/hpfb.c b/drivers/video/hpfb.c index c8e280f1bb0b..ebf8495ff198 100644 --- a/drivers/video/hpfb.c +++ b/drivers/video/hpfb.c | |||
@@ -321,11 +321,11 @@ static int __devinit hpfb_dio_probe(struct dio_dev * d, const struct dio_device_ | |||
321 | unsigned long paddr, vaddr; | 321 | unsigned long paddr, vaddr; |
322 | 322 | ||
323 | paddr = d->resource.start; | 323 | paddr = d->resource.start; |
324 | if (!request_mem_region(d->resource.start, d->resource.end - d->resource.start, d->name)) | 324 | if (!request_mem_region(d->resource.start, resource_size(&d->resource), d->name)) |
325 | return -EBUSY; | 325 | return -EBUSY; |
326 | 326 | ||
327 | if (d->scode >= DIOII_SCBASE) { | 327 | if (d->scode >= DIOII_SCBASE) { |
328 | vaddr = (unsigned long)ioremap(paddr, d->resource.end - d->resource.start); | 328 | vaddr = (unsigned long)ioremap(paddr, resource_size(&d->resource)); |
329 | } else { | 329 | } else { |
330 | vaddr = paddr + DIO_VIRADDRBASE; | 330 | vaddr = paddr + DIO_VIRADDRBASE; |
331 | } | 331 | } |
@@ -344,7 +344,7 @@ static void __devexit hpfb_remove_one(struct dio_dev *d) | |||
344 | unregister_framebuffer(&fb_info); | 344 | unregister_framebuffer(&fb_info); |
345 | if (d->scode >= DIOII_SCBASE) | 345 | if (d->scode >= DIOII_SCBASE) |
346 | iounmap((void *)fb_regs); | 346 | iounmap((void *)fb_regs); |
347 | release_mem_region(d->resource.start, d->resource.end - d->resource.start); | 347 | release_mem_region(d->resource.start, resource_size(&d->resource)); |
348 | } | 348 | } |
349 | 349 | ||
350 | static struct dio_device_id hpfb_dio_tbl[] = { | 350 | static struct dio_device_id hpfb_dio_tbl[] = { |
diff --git a/drivers/video/metronomefb.c b/drivers/video/metronomefb.c index 63ed3b72b01c..ed64edfd2c43 100644 --- a/drivers/video/metronomefb.c +++ b/drivers/video/metronomefb.c | |||
@@ -765,7 +765,7 @@ static int __devexit metronomefb_remove(struct platform_device *dev) | |||
765 | 765 | ||
766 | static struct platform_driver metronomefb_driver = { | 766 | static struct platform_driver metronomefb_driver = { |
767 | .probe = metronomefb_probe, | 767 | .probe = metronomefb_probe, |
768 | .remove = metronomefb_remove, | 768 | .remove = __devexit_p(metronomefb_remove), |
769 | .driver = { | 769 | .driver = { |
770 | .owner = THIS_MODULE, | 770 | .owner = THIS_MODULE, |
771 | .name = "metronomefb", | 771 | .name = "metronomefb", |
diff --git a/drivers/video/omap/Kconfig b/drivers/video/omap/Kconfig index 083c8fe53e24..15e7f1912af9 100644 --- a/drivers/video/omap/Kconfig +++ b/drivers/video/omap/Kconfig | |||
@@ -5,13 +5,18 @@ config FB_OMAP | |||
5 | select FB_CFB_FILLRECT | 5 | select FB_CFB_FILLRECT |
6 | select FB_CFB_COPYAREA | 6 | select FB_CFB_COPYAREA |
7 | select FB_CFB_IMAGEBLIT | 7 | select FB_CFB_IMAGEBLIT |
8 | select TWL4030_CORE if MACH_OMAP_2430SDP | ||
8 | help | 9 | help |
9 | Frame buffer driver for OMAP based boards. | 10 | Frame buffer driver for OMAP based boards. |
10 | 11 | ||
11 | config FB_OMAP_LCD_VGA | 12 | config FB_OMAP_LCD_VGA |
12 | bool "Use LCD in VGA mode" | 13 | bool "Use LCD in VGA mode" |
13 | depends on MACH_OMAP_3430SDP || MACH_OMAP_LDP | 14 | depends on MACH_OMAP_3430SDP || MACH_OMAP_LDP |
14 | 15 | help | |
16 | Set LCD resolution as VGA (640 X 480). | ||
17 | Default resolution without this option is QVGA(320 X 240). | ||
18 | Please take a look at drivers/video/omap/lcd_ldp.c file | ||
19 | for lcd driver code. | ||
15 | choice | 20 | choice |
16 | depends on FB_OMAP && MACH_OVERO | 21 | depends on FB_OMAP && MACH_OVERO |
17 | prompt "Screen resolution" | 22 | prompt "Screen resolution" |
diff --git a/drivers/video/omap/blizzard.c b/drivers/video/omap/blizzard.c index 87785c215a52..c0504a8a5079 100644 --- a/drivers/video/omap/blizzard.c +++ b/drivers/video/omap/blizzard.c | |||
@@ -397,8 +397,7 @@ static inline void free_req(struct blizzard_request *req) | |||
397 | 397 | ||
398 | spin_lock_irqsave(&blizzard.req_lock, flags); | 398 | spin_lock_irqsave(&blizzard.req_lock, flags); |
399 | 399 | ||
400 | list_del(&req->entry); | 400 | list_move(&req->entry, &blizzard.free_req_list); |
401 | list_add(&req->entry, &blizzard.free_req_list); | ||
402 | if (!(req->flags & REQ_FROM_IRQ_POOL)) | 401 | if (!(req->flags & REQ_FROM_IRQ_POOL)) |
403 | up(&blizzard.req_sema); | 402 | up(&blizzard.req_sema); |
404 | 403 | ||
diff --git a/drivers/video/omap/hwa742.c b/drivers/video/omap/hwa742.c index 0016f77cd13f..084aa0ac562b 100644 --- a/drivers/video/omap/hwa742.c +++ b/drivers/video/omap/hwa742.c | |||
@@ -269,8 +269,7 @@ static inline void free_req(struct hwa742_request *req) | |||
269 | 269 | ||
270 | spin_lock_irqsave(&hwa742.req_lock, flags); | 270 | spin_lock_irqsave(&hwa742.req_lock, flags); |
271 | 271 | ||
272 | list_del(&req->entry); | 272 | list_move(&req->entry, &hwa742.free_req_list); |
273 | list_add(&req->entry, &hwa742.free_req_list); | ||
274 | if (!(req->flags & REQ_FROM_IRQ_POOL)) | 273 | if (!(req->flags & REQ_FROM_IRQ_POOL)) |
275 | up(&hwa742.req_sema); | 274 | up(&hwa742.req_sema); |
276 | 275 | ||
diff --git a/drivers/video/omap2/displays/Kconfig b/drivers/video/omap2/displays/Kconfig index 940cab394c2e..d18ad6b2372a 100644 --- a/drivers/video/omap2/displays/Kconfig +++ b/drivers/video/omap2/displays/Kconfig | |||
@@ -9,6 +9,12 @@ config PANEL_GENERIC_DPI | |||
9 | Supports LCD Panel used in TI SDP3430 and EVM boards, | 9 | Supports LCD Panel used in TI SDP3430 and EVM boards, |
10 | OMAP3517 EVM boards and CM-T35. | 10 | OMAP3517 EVM boards and CM-T35. |
11 | 11 | ||
12 | config PANEL_LGPHILIPS_LB035Q02 | ||
13 | tristate "LG.Philips LB035Q02 LCD Panel" | ||
14 | depends on OMAP2_DSS && SPI | ||
15 | help | ||
16 | LCD Panel used on the Gumstix Overo Palo35 | ||
17 | |||
12 | config PANEL_SHARP_LS037V7DW01 | 18 | config PANEL_SHARP_LS037V7DW01 |
13 | tristate "Sharp LS037V7DW01 LCD Panel" | 19 | tristate "Sharp LS037V7DW01 LCD Panel" |
14 | depends on OMAP2_DSS | 20 | depends on OMAP2_DSS |
diff --git a/drivers/video/omap2/displays/Makefile b/drivers/video/omap2/displays/Makefile index 861f0255ec6b..0f601ab3abf4 100644 --- a/drivers/video/omap2/displays/Makefile +++ b/drivers/video/omap2/displays/Makefile | |||
@@ -1,4 +1,5 @@ | |||
1 | obj-$(CONFIG_PANEL_GENERIC_DPI) += panel-generic-dpi.o | 1 | obj-$(CONFIG_PANEL_GENERIC_DPI) += panel-generic-dpi.o |
2 | obj-$(CONFIG_PANEL_LGPHILIPS_LB035Q02) += panel-lgphilips-lb035q02.o | ||
2 | obj-$(CONFIG_PANEL_SHARP_LS037V7DW01) += panel-sharp-ls037v7dw01.o | 3 | obj-$(CONFIG_PANEL_SHARP_LS037V7DW01) += panel-sharp-ls037v7dw01.o |
3 | obj-$(CONFIG_PANEL_NEC_NL8048HL11_01B) += panel-nec-nl8048hl11-01b.o | 4 | obj-$(CONFIG_PANEL_NEC_NL8048HL11_01B) += panel-nec-nl8048hl11-01b.o |
4 | 5 | ||
diff --git a/drivers/video/omap2/displays/panel-generic-dpi.c b/drivers/video/omap2/displays/panel-generic-dpi.c index 07eb30ee59c8..4a9b9ff59467 100644 --- a/drivers/video/omap2/displays/panel-generic-dpi.c +++ b/drivers/video/omap2/displays/panel-generic-dpi.c | |||
@@ -156,6 +156,31 @@ static struct panel_config generic_dpi_panels[] = { | |||
156 | .power_off_delay = 0, | 156 | .power_off_delay = 0, |
157 | .name = "toppoly_tdo35s", | 157 | .name = "toppoly_tdo35s", |
158 | }, | 158 | }, |
159 | |||
160 | /* Samsung LTE430WQ-F0C */ | ||
161 | { | ||
162 | { | ||
163 | .x_res = 480, | ||
164 | .y_res = 272, | ||
165 | |||
166 | .pixel_clock = 9200, | ||
167 | |||
168 | .hfp = 8, | ||
169 | .hsw = 41, | ||
170 | .hbp = 45 - 41, | ||
171 | |||
172 | .vfp = 4, | ||
173 | .vsw = 10, | ||
174 | .vbp = 12 - 10, | ||
175 | }, | ||
176 | .acbi = 0x0, | ||
177 | .acb = 0x0, | ||
178 | .config = OMAP_DSS_LCD_TFT | OMAP_DSS_LCD_IVS | | ||
179 | OMAP_DSS_LCD_IHS, | ||
180 | .power_on_delay = 0, | ||
181 | .power_off_delay = 0, | ||
182 | .name = "samsung_lte430wq_f0c", | ||
183 | }, | ||
159 | }; | 184 | }; |
160 | 185 | ||
161 | struct panel_drv_data { | 186 | struct panel_drv_data { |
diff --git a/drivers/video/omap2/displays/panel-lgphilips-lb035q02.c b/drivers/video/omap2/displays/panel-lgphilips-lb035q02.c new file mode 100644 index 000000000000..271324db2436 --- /dev/null +++ b/drivers/video/omap2/displays/panel-lgphilips-lb035q02.c | |||
@@ -0,0 +1,279 @@ | |||
1 | /* | ||
2 | * LCD panel driver for LG.Philips LB035Q02 | ||
3 | * | ||
4 | * Author: Steve Sakoman <steve@sakoman.com> | ||
5 | * | ||
6 | * This program is free software; you can redistribute it and/or modify it | ||
7 | * under the terms of the GNU General Public License version 2 as published by | ||
8 | * the Free Software Foundation. | ||
9 | * | ||
10 | * This program is distributed in the hope that it will be useful, but WITHOUT | ||
11 | * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or | ||
12 | * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for | ||
13 | * more details. | ||
14 | * | ||
15 | * You should have received a copy of the GNU General Public License along with | ||
16 | * this program. If not, see <http://www.gnu.org/licenses/>. | ||
17 | */ | ||
18 | |||
19 | #include <linux/module.h> | ||
20 | #include <linux/delay.h> | ||
21 | #include <linux/spi/spi.h> | ||
22 | #include <linux/mutex.h> | ||
23 | |||
24 | #include <plat/display.h> | ||
25 | |||
26 | struct lb035q02_data { | ||
27 | struct mutex lock; | ||
28 | }; | ||
29 | |||
30 | static struct omap_video_timings lb035q02_timings = { | ||
31 | .x_res = 320, | ||
32 | .y_res = 240, | ||
33 | |||
34 | .pixel_clock = 6500, | ||
35 | |||
36 | .hsw = 2, | ||
37 | .hfp = 20, | ||
38 | .hbp = 68, | ||
39 | |||
40 | .vsw = 2, | ||
41 | .vfp = 4, | ||
42 | .vbp = 18, | ||
43 | }; | ||
44 | |||
45 | static int lb035q02_panel_power_on(struct omap_dss_device *dssdev) | ||
46 | { | ||
47 | int r; | ||
48 | |||
49 | if (dssdev->state == OMAP_DSS_DISPLAY_ACTIVE) | ||
50 | return 0; | ||
51 | |||
52 | r = omapdss_dpi_display_enable(dssdev); | ||
53 | if (r) | ||
54 | goto err0; | ||
55 | |||
56 | if (dssdev->platform_enable) { | ||
57 | r = dssdev->platform_enable(dssdev); | ||
58 | if (r) | ||
59 | goto err1; | ||
60 | } | ||
61 | |||
62 | return 0; | ||
63 | err1: | ||
64 | omapdss_dpi_display_disable(dssdev); | ||
65 | err0: | ||
66 | return r; | ||
67 | } | ||
68 | |||
69 | static void lb035q02_panel_power_off(struct omap_dss_device *dssdev) | ||
70 | { | ||
71 | if (dssdev->state != OMAP_DSS_DISPLAY_ACTIVE) | ||
72 | return; | ||
73 | |||
74 | if (dssdev->platform_disable) | ||
75 | dssdev->platform_disable(dssdev); | ||
76 | |||
77 | omapdss_dpi_display_disable(dssdev); | ||
78 | } | ||
79 | |||
80 | static int lb035q02_panel_probe(struct omap_dss_device *dssdev) | ||
81 | { | ||
82 | struct lb035q02_data *ld; | ||
83 | int r; | ||
84 | |||
85 | dssdev->panel.config = OMAP_DSS_LCD_TFT | OMAP_DSS_LCD_IVS | | ||
86 | OMAP_DSS_LCD_IHS; | ||
87 | dssdev->panel.timings = lb035q02_timings; | ||
88 | |||
89 | ld = kzalloc(sizeof(*ld), GFP_KERNEL); | ||
90 | if (!ld) { | ||
91 | r = -ENOMEM; | ||
92 | goto err; | ||
93 | } | ||
94 | mutex_init(&ld->lock); | ||
95 | dev_set_drvdata(&dssdev->dev, ld); | ||
96 | return 0; | ||
97 | err: | ||
98 | return r; | ||
99 | } | ||
100 | |||
101 | static void lb035q02_panel_remove(struct omap_dss_device *dssdev) | ||
102 | { | ||
103 | struct lb035q02_data *ld = dev_get_drvdata(&dssdev->dev); | ||
104 | |||
105 | kfree(ld); | ||
106 | } | ||
107 | |||
108 | static int lb035q02_panel_enable(struct omap_dss_device *dssdev) | ||
109 | { | ||
110 | struct lb035q02_data *ld = dev_get_drvdata(&dssdev->dev); | ||
111 | int r; | ||
112 | |||
113 | mutex_lock(&ld->lock); | ||
114 | |||
115 | r = lb035q02_panel_power_on(dssdev); | ||
116 | if (r) | ||
117 | goto err; | ||
118 | dssdev->state = OMAP_DSS_DISPLAY_ACTIVE; | ||
119 | |||
120 | mutex_unlock(&ld->lock); | ||
121 | return 0; | ||
122 | err: | ||
123 | mutex_unlock(&ld->lock); | ||
124 | return r; | ||
125 | } | ||
126 | |||
127 | static void lb035q02_panel_disable(struct omap_dss_device *dssdev) | ||
128 | { | ||
129 | struct lb035q02_data *ld = dev_get_drvdata(&dssdev->dev); | ||
130 | |||
131 | mutex_lock(&ld->lock); | ||
132 | |||
133 | lb035q02_panel_power_off(dssdev); | ||
134 | dssdev->state = OMAP_DSS_DISPLAY_DISABLED; | ||
135 | |||
136 | mutex_unlock(&ld->lock); | ||
137 | } | ||
138 | |||
139 | static int lb035q02_panel_suspend(struct omap_dss_device *dssdev) | ||
140 | { | ||
141 | struct lb035q02_data *ld = dev_get_drvdata(&dssdev->dev); | ||
142 | |||
143 | mutex_lock(&ld->lock); | ||
144 | |||
145 | lb035q02_panel_power_off(dssdev); | ||
146 | dssdev->state = OMAP_DSS_DISPLAY_SUSPENDED; | ||
147 | |||
148 | mutex_unlock(&ld->lock); | ||
149 | return 0; | ||
150 | } | ||
151 | |||
152 | static int lb035q02_panel_resume(struct omap_dss_device *dssdev) | ||
153 | { | ||
154 | struct lb035q02_data *ld = dev_get_drvdata(&dssdev->dev); | ||
155 | int r; | ||
156 | |||
157 | mutex_lock(&ld->lock); | ||
158 | |||
159 | r = lb035q02_panel_power_on(dssdev); | ||
160 | if (r) | ||
161 | goto err; | ||
162 | dssdev->state = OMAP_DSS_DISPLAY_ACTIVE; | ||
163 | |||
164 | mutex_unlock(&ld->lock); | ||
165 | return 0; | ||
166 | err: | ||
167 | mutex_unlock(&ld->lock); | ||
168 | return r; | ||
169 | } | ||
170 | |||
171 | static struct omap_dss_driver lb035q02_driver = { | ||
172 | .probe = lb035q02_panel_probe, | ||
173 | .remove = lb035q02_panel_remove, | ||
174 | |||
175 | .enable = lb035q02_panel_enable, | ||
176 | .disable = lb035q02_panel_disable, | ||
177 | .suspend = lb035q02_panel_suspend, | ||
178 | .resume = lb035q02_panel_resume, | ||
179 | |||
180 | .driver = { | ||
181 | .name = "lgphilips_lb035q02_panel", | ||
182 | .owner = THIS_MODULE, | ||
183 | }, | ||
184 | }; | ||
185 | |||
186 | static int lb035q02_write_reg(struct spi_device *spi, u8 reg, u16 val) | ||
187 | { | ||
188 | struct spi_message msg; | ||
189 | struct spi_transfer index_xfer = { | ||
190 | .len = 3, | ||
191 | .cs_change = 1, | ||
192 | }; | ||
193 | struct spi_transfer value_xfer = { | ||
194 | .len = 3, | ||
195 | }; | ||
196 | u8 buffer[16]; | ||
197 | |||
198 | spi_message_init(&msg); | ||
199 | |||
200 | /* register index */ | ||
201 | buffer[0] = 0x70; | ||
202 | buffer[1] = 0x00; | ||
203 | buffer[2] = reg & 0x7f; | ||
204 | index_xfer.tx_buf = buffer; | ||
205 | spi_message_add_tail(&index_xfer, &msg); | ||
206 | |||
207 | /* register value */ | ||
208 | buffer[4] = 0x72; | ||
209 | buffer[5] = val >> 8; | ||
210 | buffer[6] = val; | ||
211 | value_xfer.tx_buf = buffer + 4; | ||
212 | spi_message_add_tail(&value_xfer, &msg); | ||
213 | |||
214 | return spi_sync(spi, &msg); | ||
215 | } | ||
216 | |||
217 | static void init_lb035q02_panel(struct spi_device *spi) | ||
218 | { | ||
219 | /* Init sequence from page 28 of the lb035q02 spec */ | ||
220 | lb035q02_write_reg(spi, 0x01, 0x6300); | ||
221 | lb035q02_write_reg(spi, 0x02, 0x0200); | ||
222 | lb035q02_write_reg(spi, 0x03, 0x0177); | ||
223 | lb035q02_write_reg(spi, 0x04, 0x04c7); | ||
224 | lb035q02_write_reg(spi, 0x05, 0xffc0); | ||
225 | lb035q02_write_reg(spi, 0x06, 0xe806); | ||
226 | lb035q02_write_reg(spi, 0x0a, 0x4008); | ||
227 | lb035q02_write_reg(spi, 0x0b, 0x0000); | ||
228 | lb035q02_write_reg(spi, 0x0d, 0x0030); | ||
229 | lb035q02_write_reg(spi, 0x0e, 0x2800); | ||
230 | lb035q02_write_reg(spi, 0x0f, 0x0000); | ||
231 | lb035q02_write_reg(spi, 0x16, 0x9f80); | ||
232 | lb035q02_write_reg(spi, 0x17, 0x0a0f); | ||
233 | lb035q02_write_reg(spi, 0x1e, 0x00c1); | ||
234 | lb035q02_write_reg(spi, 0x30, 0x0300); | ||
235 | lb035q02_write_reg(spi, 0x31, 0x0007); | ||
236 | lb035q02_write_reg(spi, 0x32, 0x0000); | ||
237 | lb035q02_write_reg(spi, 0x33, 0x0000); | ||
238 | lb035q02_write_reg(spi, 0x34, 0x0707); | ||
239 | lb035q02_write_reg(spi, 0x35, 0x0004); | ||
240 | lb035q02_write_reg(spi, 0x36, 0x0302); | ||
241 | lb035q02_write_reg(spi, 0x37, 0x0202); | ||
242 | lb035q02_write_reg(spi, 0x3a, 0x0a0d); | ||
243 | lb035q02_write_reg(spi, 0x3b, 0x0806); | ||
244 | } | ||
245 | |||
246 | static int __devinit lb035q02_panel_spi_probe(struct spi_device *spi) | ||
247 | { | ||
248 | init_lb035q02_panel(spi); | ||
249 | return omap_dss_register_driver(&lb035q02_driver); | ||
250 | } | ||
251 | |||
252 | static int __devexit lb035q02_panel_spi_remove(struct spi_device *spi) | ||
253 | { | ||
254 | omap_dss_unregister_driver(&lb035q02_driver); | ||
255 | return 0; | ||
256 | } | ||
257 | |||
258 | static struct spi_driver lb035q02_spi_driver = { | ||
259 | .driver = { | ||
260 | .name = "lgphilips_lb035q02_panel-spi", | ||
261 | .owner = THIS_MODULE, | ||
262 | }, | ||
263 | .probe = lb035q02_panel_spi_probe, | ||
264 | .remove = __devexit_p(lb035q02_panel_spi_remove), | ||
265 | }; | ||
266 | |||
267 | static int __init lb035q02_panel_drv_init(void) | ||
268 | { | ||
269 | return spi_register_driver(&lb035q02_spi_driver); | ||
270 | } | ||
271 | |||
272 | static void __exit lb035q02_panel_drv_exit(void) | ||
273 | { | ||
274 | spi_unregister_driver(&lb035q02_spi_driver); | ||
275 | } | ||
276 | |||
277 | module_init(lb035q02_panel_drv_init); | ||
278 | module_exit(lb035q02_panel_drv_exit); | ||
279 | MODULE_LICENSE("GPL"); | ||
diff --git a/drivers/video/omap2/displays/panel-taal.c b/drivers/video/omap2/displays/panel-taal.c index c74e8b778ba1..adc9900458e1 100644 --- a/drivers/video/omap2/displays/panel-taal.c +++ b/drivers/video/omap2/displays/panel-taal.c | |||
@@ -218,6 +218,8 @@ struct taal_data { | |||
218 | u16 w; | 218 | u16 w; |
219 | u16 h; | 219 | u16 h; |
220 | } update_region; | 220 | } update_region; |
221 | int channel; | ||
222 | |||
221 | struct delayed_work te_timeout_work; | 223 | struct delayed_work te_timeout_work; |
222 | 224 | ||
223 | bool use_dsi_bl; | 225 | bool use_dsi_bl; |
@@ -257,12 +259,12 @@ static void hw_guard_wait(struct taal_data *td) | |||
257 | } | 259 | } |
258 | } | 260 | } |
259 | 261 | ||
260 | static int taal_dcs_read_1(u8 dcs_cmd, u8 *data) | 262 | static int taal_dcs_read_1(struct taal_data *td, u8 dcs_cmd, u8 *data) |
261 | { | 263 | { |
262 | int r; | 264 | int r; |
263 | u8 buf[1]; | 265 | u8 buf[1]; |
264 | 266 | ||
265 | r = dsi_vc_dcs_read(TCH, dcs_cmd, buf, 1); | 267 | r = dsi_vc_dcs_read(td->channel, dcs_cmd, buf, 1); |
266 | 268 | ||
267 | if (r < 0) | 269 | if (r < 0) |
268 | return r; | 270 | return r; |
@@ -272,17 +274,17 @@ static int taal_dcs_read_1(u8 dcs_cmd, u8 *data) | |||
272 | return 0; | 274 | return 0; |
273 | } | 275 | } |
274 | 276 | ||
275 | static int taal_dcs_write_0(u8 dcs_cmd) | 277 | static int taal_dcs_write_0(struct taal_data *td, u8 dcs_cmd) |
276 | { | 278 | { |
277 | return dsi_vc_dcs_write(TCH, &dcs_cmd, 1); | 279 | return dsi_vc_dcs_write(td->channel, &dcs_cmd, 1); |
278 | } | 280 | } |
279 | 281 | ||
280 | static int taal_dcs_write_1(u8 dcs_cmd, u8 param) | 282 | static int taal_dcs_write_1(struct taal_data *td, u8 dcs_cmd, u8 param) |
281 | { | 283 | { |
282 | u8 buf[2]; | 284 | u8 buf[2]; |
283 | buf[0] = dcs_cmd; | 285 | buf[0] = dcs_cmd; |
284 | buf[1] = param; | 286 | buf[1] = param; |
285 | return dsi_vc_dcs_write(TCH, buf, 2); | 287 | return dsi_vc_dcs_write(td->channel, buf, 2); |
286 | } | 288 | } |
287 | 289 | ||
288 | static int taal_sleep_in(struct taal_data *td) | 290 | static int taal_sleep_in(struct taal_data *td) |
@@ -294,7 +296,7 @@ static int taal_sleep_in(struct taal_data *td) | |||
294 | hw_guard_wait(td); | 296 | hw_guard_wait(td); |
295 | 297 | ||
296 | cmd = DCS_SLEEP_IN; | 298 | cmd = DCS_SLEEP_IN; |
297 | r = dsi_vc_dcs_write_nosync(TCH, &cmd, 1); | 299 | r = dsi_vc_dcs_write_nosync(td->channel, &cmd, 1); |
298 | if (r) | 300 | if (r) |
299 | return r; | 301 | return r; |
300 | 302 | ||
@@ -312,7 +314,7 @@ static int taal_sleep_out(struct taal_data *td) | |||
312 | 314 | ||
313 | hw_guard_wait(td); | 315 | hw_guard_wait(td); |
314 | 316 | ||
315 | r = taal_dcs_write_0(DCS_SLEEP_OUT); | 317 | r = taal_dcs_write_0(td, DCS_SLEEP_OUT); |
316 | if (r) | 318 | if (r) |
317 | return r; | 319 | return r; |
318 | 320 | ||
@@ -324,30 +326,30 @@ static int taal_sleep_out(struct taal_data *td) | |||
324 | return 0; | 326 | return 0; |
325 | } | 327 | } |
326 | 328 | ||
327 | static int taal_get_id(u8 *id1, u8 *id2, u8 *id3) | 329 | static int taal_get_id(struct taal_data *td, u8 *id1, u8 *id2, u8 *id3) |
328 | { | 330 | { |
329 | int r; | 331 | int r; |
330 | 332 | ||
331 | r = taal_dcs_read_1(DCS_GET_ID1, id1); | 333 | r = taal_dcs_read_1(td, DCS_GET_ID1, id1); |
332 | if (r) | 334 | if (r) |
333 | return r; | 335 | return r; |
334 | r = taal_dcs_read_1(DCS_GET_ID2, id2); | 336 | r = taal_dcs_read_1(td, DCS_GET_ID2, id2); |
335 | if (r) | 337 | if (r) |
336 | return r; | 338 | return r; |
337 | r = taal_dcs_read_1(DCS_GET_ID3, id3); | 339 | r = taal_dcs_read_1(td, DCS_GET_ID3, id3); |
338 | if (r) | 340 | if (r) |
339 | return r; | 341 | return r; |
340 | 342 | ||
341 | return 0; | 343 | return 0; |
342 | } | 344 | } |
343 | 345 | ||
344 | static int taal_set_addr_mode(u8 rotate, bool mirror) | 346 | static int taal_set_addr_mode(struct taal_data *td, u8 rotate, bool mirror) |
345 | { | 347 | { |
346 | int r; | 348 | int r; |
347 | u8 mode; | 349 | u8 mode; |
348 | int b5, b6, b7; | 350 | int b5, b6, b7; |
349 | 351 | ||
350 | r = taal_dcs_read_1(DCS_READ_MADCTL, &mode); | 352 | r = taal_dcs_read_1(td, DCS_READ_MADCTL, &mode); |
351 | if (r) | 353 | if (r) |
352 | return r; | 354 | return r; |
353 | 355 | ||
@@ -381,10 +383,11 @@ static int taal_set_addr_mode(u8 rotate, bool mirror) | |||
381 | mode &= ~((1<<7) | (1<<6) | (1<<5)); | 383 | mode &= ~((1<<7) | (1<<6) | (1<<5)); |
382 | mode |= (b7 << 7) | (b6 << 6) | (b5 << 5); | 384 | mode |= (b7 << 7) | (b6 << 6) | (b5 << 5); |
383 | 385 | ||
384 | return taal_dcs_write_1(DCS_MEM_ACC_CTRL, mode); | 386 | return taal_dcs_write_1(td, DCS_MEM_ACC_CTRL, mode); |
385 | } | 387 | } |
386 | 388 | ||
387 | static int taal_set_update_window(u16 x, u16 y, u16 w, u16 h) | 389 | static int taal_set_update_window(struct taal_data *td, |
390 | u16 x, u16 y, u16 w, u16 h) | ||
388 | { | 391 | { |
389 | int r; | 392 | int r; |
390 | u16 x1 = x; | 393 | u16 x1 = x; |
@@ -399,7 +402,7 @@ static int taal_set_update_window(u16 x, u16 y, u16 w, u16 h) | |||
399 | buf[3] = (x2 >> 8) & 0xff; | 402 | buf[3] = (x2 >> 8) & 0xff; |
400 | buf[4] = (x2 >> 0) & 0xff; | 403 | buf[4] = (x2 >> 0) & 0xff; |
401 | 404 | ||
402 | r = dsi_vc_dcs_write_nosync(TCH, buf, sizeof(buf)); | 405 | r = dsi_vc_dcs_write_nosync(td->channel, buf, sizeof(buf)); |
403 | if (r) | 406 | if (r) |
404 | return r; | 407 | return r; |
405 | 408 | ||
@@ -409,11 +412,11 @@ static int taal_set_update_window(u16 x, u16 y, u16 w, u16 h) | |||
409 | buf[3] = (y2 >> 8) & 0xff; | 412 | buf[3] = (y2 >> 8) & 0xff; |
410 | buf[4] = (y2 >> 0) & 0xff; | 413 | buf[4] = (y2 >> 0) & 0xff; |
411 | 414 | ||
412 | r = dsi_vc_dcs_write_nosync(TCH, buf, sizeof(buf)); | 415 | r = dsi_vc_dcs_write_nosync(td->channel, buf, sizeof(buf)); |
413 | if (r) | 416 | if (r) |
414 | return r; | 417 | return r; |
415 | 418 | ||
416 | dsi_vc_send_bta_sync(TCH); | 419 | dsi_vc_send_bta_sync(td->channel); |
417 | 420 | ||
418 | return r; | 421 | return r; |
419 | } | 422 | } |
@@ -439,7 +442,7 @@ static int taal_bl_update_status(struct backlight_device *dev) | |||
439 | if (td->use_dsi_bl) { | 442 | if (td->use_dsi_bl) { |
440 | if (td->enabled) { | 443 | if (td->enabled) { |
441 | dsi_bus_lock(); | 444 | dsi_bus_lock(); |
442 | r = taal_dcs_write_1(DCS_BRIGHTNESS, level); | 445 | r = taal_dcs_write_1(td, DCS_BRIGHTNESS, level); |
443 | dsi_bus_unlock(); | 446 | dsi_bus_unlock(); |
444 | } else { | 447 | } else { |
445 | r = 0; | 448 | r = 0; |
@@ -502,7 +505,7 @@ static ssize_t taal_num_errors_show(struct device *dev, | |||
502 | 505 | ||
503 | if (td->enabled) { | 506 | if (td->enabled) { |
504 | dsi_bus_lock(); | 507 | dsi_bus_lock(); |
505 | r = taal_dcs_read_1(DCS_READ_NUM_ERRORS, &errors); | 508 | r = taal_dcs_read_1(td, DCS_READ_NUM_ERRORS, &errors); |
506 | dsi_bus_unlock(); | 509 | dsi_bus_unlock(); |
507 | } else { | 510 | } else { |
508 | r = -ENODEV; | 511 | r = -ENODEV; |
@@ -528,7 +531,7 @@ static ssize_t taal_hw_revision_show(struct device *dev, | |||
528 | 531 | ||
529 | if (td->enabled) { | 532 | if (td->enabled) { |
530 | dsi_bus_lock(); | 533 | dsi_bus_lock(); |
531 | r = taal_get_id(&id1, &id2, &id3); | 534 | r = taal_get_id(td, &id1, &id2, &id3); |
532 | dsi_bus_unlock(); | 535 | dsi_bus_unlock(); |
533 | } else { | 536 | } else { |
534 | r = -ENODEV; | 537 | r = -ENODEV; |
@@ -590,7 +593,7 @@ static ssize_t store_cabc_mode(struct device *dev, | |||
590 | if (td->enabled) { | 593 | if (td->enabled) { |
591 | dsi_bus_lock(); | 594 | dsi_bus_lock(); |
592 | if (!td->cabc_broken) | 595 | if (!td->cabc_broken) |
593 | taal_dcs_write_1(DCS_WRITE_CABC, i); | 596 | taal_dcs_write_1(td, DCS_WRITE_CABC, i); |
594 | dsi_bus_unlock(); | 597 | dsi_bus_unlock(); |
595 | } | 598 | } |
596 | 599 | ||
@@ -776,14 +779,29 @@ static int taal_probe(struct omap_dss_device *dssdev) | |||
776 | dev_dbg(&dssdev->dev, "Using GPIO TE\n"); | 779 | dev_dbg(&dssdev->dev, "Using GPIO TE\n"); |
777 | } | 780 | } |
778 | 781 | ||
782 | r = omap_dsi_request_vc(dssdev, &td->channel); | ||
783 | if (r) { | ||
784 | dev_err(&dssdev->dev, "failed to get virtual channel\n"); | ||
785 | goto err_req_vc; | ||
786 | } | ||
787 | |||
788 | r = omap_dsi_set_vc_id(dssdev, td->channel, TCH); | ||
789 | if (r) { | ||
790 | dev_err(&dssdev->dev, "failed to set VC_ID\n"); | ||
791 | goto err_vc_id; | ||
792 | } | ||
793 | |||
779 | r = sysfs_create_group(&dssdev->dev.kobj, &taal_attr_group); | 794 | r = sysfs_create_group(&dssdev->dev.kobj, &taal_attr_group); |
780 | if (r) { | 795 | if (r) { |
781 | dev_err(&dssdev->dev, "failed to create sysfs files\n"); | 796 | dev_err(&dssdev->dev, "failed to create sysfs files\n"); |
782 | goto err_sysfs; | 797 | goto err_vc_id; |
783 | } | 798 | } |
784 | 799 | ||
785 | return 0; | 800 | return 0; |
786 | err_sysfs: | 801 | |
802 | err_vc_id: | ||
803 | omap_dsi_release_vc(dssdev, td->channel); | ||
804 | err_req_vc: | ||
787 | if (panel_data->use_ext_te) | 805 | if (panel_data->use_ext_te) |
788 | free_irq(gpio_to_irq(panel_data->ext_te_gpio), dssdev); | 806 | free_irq(gpio_to_irq(panel_data->ext_te_gpio), dssdev); |
789 | err_irq: | 807 | err_irq: |
@@ -810,6 +828,7 @@ static void taal_remove(struct omap_dss_device *dssdev) | |||
810 | dev_dbg(&dssdev->dev, "remove\n"); | 828 | dev_dbg(&dssdev->dev, "remove\n"); |
811 | 829 | ||
812 | sysfs_remove_group(&dssdev->dev.kobj, &taal_attr_group); | 830 | sysfs_remove_group(&dssdev->dev.kobj, &taal_attr_group); |
831 | omap_dsi_release_vc(dssdev, td->channel); | ||
813 | 832 | ||
814 | if (panel_data->use_ext_te) { | 833 | if (panel_data->use_ext_te) { |
815 | int gpio = panel_data->ext_te_gpio; | 834 | int gpio = panel_data->ext_te_gpio; |
@@ -848,13 +867,13 @@ static int taal_power_on(struct omap_dss_device *dssdev) | |||
848 | 867 | ||
849 | taal_hw_reset(dssdev); | 868 | taal_hw_reset(dssdev); |
850 | 869 | ||
851 | omapdss_dsi_vc_enable_hs(TCH, false); | 870 | omapdss_dsi_vc_enable_hs(td->channel, false); |
852 | 871 | ||
853 | r = taal_sleep_out(td); | 872 | r = taal_sleep_out(td); |
854 | if (r) | 873 | if (r) |
855 | goto err; | 874 | goto err; |
856 | 875 | ||
857 | r = taal_get_id(&id1, &id2, &id3); | 876 | r = taal_get_id(td, &id1, &id2, &id3); |
858 | if (r) | 877 | if (r) |
859 | goto err; | 878 | goto err; |
860 | 879 | ||
@@ -863,30 +882,30 @@ static int taal_power_on(struct omap_dss_device *dssdev) | |||
863 | (id2 == 0x00 || id2 == 0xff || id2 == 0x81)) | 882 | (id2 == 0x00 || id2 == 0xff || id2 == 0x81)) |
864 | td->cabc_broken = true; | 883 | td->cabc_broken = true; |
865 | 884 | ||
866 | r = taal_dcs_write_1(DCS_BRIGHTNESS, 0xff); | 885 | r = taal_dcs_write_1(td, DCS_BRIGHTNESS, 0xff); |
867 | if (r) | 886 | if (r) |
868 | goto err; | 887 | goto err; |
869 | 888 | ||
870 | r = taal_dcs_write_1(DCS_CTRL_DISPLAY, | 889 | r = taal_dcs_write_1(td, DCS_CTRL_DISPLAY, |
871 | (1<<2) | (1<<5)); /* BL | BCTRL */ | 890 | (1<<2) | (1<<5)); /* BL | BCTRL */ |
872 | if (r) | 891 | if (r) |
873 | goto err; | 892 | goto err; |
874 | 893 | ||
875 | r = taal_dcs_write_1(DCS_PIXEL_FORMAT, 0x7); /* 24bit/pixel */ | 894 | r = taal_dcs_write_1(td, DCS_PIXEL_FORMAT, 0x7); /* 24bit/pixel */ |
876 | if (r) | 895 | if (r) |
877 | goto err; | 896 | goto err; |
878 | 897 | ||
879 | r = taal_set_addr_mode(td->rotate, td->mirror); | 898 | r = taal_set_addr_mode(td, td->rotate, td->mirror); |
880 | if (r) | 899 | if (r) |
881 | goto err; | 900 | goto err; |
882 | 901 | ||
883 | if (!td->cabc_broken) { | 902 | if (!td->cabc_broken) { |
884 | r = taal_dcs_write_1(DCS_WRITE_CABC, td->cabc_mode); | 903 | r = taal_dcs_write_1(td, DCS_WRITE_CABC, td->cabc_mode); |
885 | if (r) | 904 | if (r) |
886 | goto err; | 905 | goto err; |
887 | } | 906 | } |
888 | 907 | ||
889 | r = taal_dcs_write_0(DCS_DISPLAY_ON); | 908 | r = taal_dcs_write_0(td, DCS_DISPLAY_ON); |
890 | if (r) | 909 | if (r) |
891 | goto err; | 910 | goto err; |
892 | 911 | ||
@@ -905,7 +924,7 @@ static int taal_power_on(struct omap_dss_device *dssdev) | |||
905 | td->intro_printed = true; | 924 | td->intro_printed = true; |
906 | } | 925 | } |
907 | 926 | ||
908 | omapdss_dsi_vc_enable_hs(TCH, true); | 927 | omapdss_dsi_vc_enable_hs(td->channel, true); |
909 | 928 | ||
910 | return 0; | 929 | return 0; |
911 | err: | 930 | err: |
@@ -923,7 +942,7 @@ static void taal_power_off(struct omap_dss_device *dssdev) | |||
923 | struct taal_data *td = dev_get_drvdata(&dssdev->dev); | 942 | struct taal_data *td = dev_get_drvdata(&dssdev->dev); |
924 | int r; | 943 | int r; |
925 | 944 | ||
926 | r = taal_dcs_write_0(DCS_DISPLAY_OFF); | 945 | r = taal_dcs_write_0(td, DCS_DISPLAY_OFF); |
927 | if (!r) { | 946 | if (!r) { |
928 | r = taal_sleep_in(td); | 947 | r = taal_sleep_in(td); |
929 | /* HACK: wait a bit so that the message goes through */ | 948 | /* HACK: wait a bit so that the message goes through */ |
@@ -1091,7 +1110,7 @@ static irqreturn_t taal_te_isr(int irq, void *data) | |||
1091 | if (old) { | 1110 | if (old) { |
1092 | cancel_delayed_work(&td->te_timeout_work); | 1111 | cancel_delayed_work(&td->te_timeout_work); |
1093 | 1112 | ||
1094 | r = omap_dsi_update(dssdev, TCH, | 1113 | r = omap_dsi_update(dssdev, td->channel, |
1095 | td->update_region.x, | 1114 | td->update_region.x, |
1096 | td->update_region.y, | 1115 | td->update_region.y, |
1097 | td->update_region.w, | 1116 | td->update_region.w, |
@@ -1141,7 +1160,7 @@ static int taal_update(struct omap_dss_device *dssdev, | |||
1141 | if (r) | 1160 | if (r) |
1142 | goto err; | 1161 | goto err; |
1143 | 1162 | ||
1144 | r = taal_set_update_window(x, y, w, h); | 1163 | r = taal_set_update_window(td, x, y, w, h); |
1145 | if (r) | 1164 | if (r) |
1146 | goto err; | 1165 | goto err; |
1147 | 1166 | ||
@@ -1155,7 +1174,7 @@ static int taal_update(struct omap_dss_device *dssdev, | |||
1155 | msecs_to_jiffies(250)); | 1174 | msecs_to_jiffies(250)); |
1156 | atomic_set(&td->do_update, 1); | 1175 | atomic_set(&td->do_update, 1); |
1157 | } else { | 1176 | } else { |
1158 | r = omap_dsi_update(dssdev, TCH, x, y, w, h, | 1177 | r = omap_dsi_update(dssdev, td->channel, x, y, w, h, |
1159 | taal_framedone_cb, dssdev); | 1178 | taal_framedone_cb, dssdev); |
1160 | if (r) | 1179 | if (r) |
1161 | goto err; | 1180 | goto err; |
@@ -1193,9 +1212,9 @@ static int _taal_enable_te(struct omap_dss_device *dssdev, bool enable) | |||
1193 | int r; | 1212 | int r; |
1194 | 1213 | ||
1195 | if (enable) | 1214 | if (enable) |
1196 | r = taal_dcs_write_1(DCS_TEAR_ON, 0); | 1215 | r = taal_dcs_write_1(td, DCS_TEAR_ON, 0); |
1197 | else | 1216 | else |
1198 | r = taal_dcs_write_0(DCS_TEAR_OFF); | 1217 | r = taal_dcs_write_0(td, DCS_TEAR_OFF); |
1199 | 1218 | ||
1200 | if (!panel_data->use_ext_te) | 1219 | if (!panel_data->use_ext_te) |
1201 | omapdss_dsi_enable_te(dssdev, enable); | 1220 | omapdss_dsi_enable_te(dssdev, enable); |
@@ -1265,7 +1284,7 @@ static int taal_rotate(struct omap_dss_device *dssdev, u8 rotate) | |||
1265 | dsi_bus_lock(); | 1284 | dsi_bus_lock(); |
1266 | 1285 | ||
1267 | if (td->enabled) { | 1286 | if (td->enabled) { |
1268 | r = taal_set_addr_mode(rotate, td->mirror); | 1287 | r = taal_set_addr_mode(td, rotate, td->mirror); |
1269 | if (r) | 1288 | if (r) |
1270 | goto err; | 1289 | goto err; |
1271 | } | 1290 | } |
@@ -1308,7 +1327,7 @@ static int taal_mirror(struct omap_dss_device *dssdev, bool enable) | |||
1308 | 1327 | ||
1309 | dsi_bus_lock(); | 1328 | dsi_bus_lock(); |
1310 | if (td->enabled) { | 1329 | if (td->enabled) { |
1311 | r = taal_set_addr_mode(td->rotate, enable); | 1330 | r = taal_set_addr_mode(td, td->rotate, enable); |
1312 | if (r) | 1331 | if (r) |
1313 | goto err; | 1332 | goto err; |
1314 | } | 1333 | } |
@@ -1352,13 +1371,13 @@ static int taal_run_test(struct omap_dss_device *dssdev, int test_num) | |||
1352 | 1371 | ||
1353 | dsi_bus_lock(); | 1372 | dsi_bus_lock(); |
1354 | 1373 | ||
1355 | r = taal_dcs_read_1(DCS_GET_ID1, &id1); | 1374 | r = taal_dcs_read_1(td, DCS_GET_ID1, &id1); |
1356 | if (r) | 1375 | if (r) |
1357 | goto err2; | 1376 | goto err2; |
1358 | r = taal_dcs_read_1(DCS_GET_ID2, &id2); | 1377 | r = taal_dcs_read_1(td, DCS_GET_ID2, &id2); |
1359 | if (r) | 1378 | if (r) |
1360 | goto err2; | 1379 | goto err2; |
1361 | r = taal_dcs_read_1(DCS_GET_ID3, &id3); | 1380 | r = taal_dcs_read_1(td, DCS_GET_ID3, &id3); |
1362 | if (r) | 1381 | if (r) |
1363 | goto err2; | 1382 | goto err2; |
1364 | 1383 | ||
@@ -1406,9 +1425,9 @@ static int taal_memory_read(struct omap_dss_device *dssdev, | |||
1406 | else | 1425 | else |
1407 | plen = 2; | 1426 | plen = 2; |
1408 | 1427 | ||
1409 | taal_set_update_window(x, y, w, h); | 1428 | taal_set_update_window(td, x, y, w, h); |
1410 | 1429 | ||
1411 | r = dsi_vc_set_max_rx_packet_size(TCH, plen); | 1430 | r = dsi_vc_set_max_rx_packet_size(td->channel, plen); |
1412 | if (r) | 1431 | if (r) |
1413 | goto err2; | 1432 | goto err2; |
1414 | 1433 | ||
@@ -1416,7 +1435,7 @@ static int taal_memory_read(struct omap_dss_device *dssdev, | |||
1416 | u8 dcs_cmd = first ? 0x2e : 0x3e; | 1435 | u8 dcs_cmd = first ? 0x2e : 0x3e; |
1417 | first = 0; | 1436 | first = 0; |
1418 | 1437 | ||
1419 | r = dsi_vc_dcs_read(TCH, dcs_cmd, | 1438 | r = dsi_vc_dcs_read(td->channel, dcs_cmd, |
1420 | buf + buf_used, size - buf_used); | 1439 | buf + buf_used, size - buf_used); |
1421 | 1440 | ||
1422 | if (r < 0) { | 1441 | if (r < 0) { |
@@ -1442,7 +1461,7 @@ static int taal_memory_read(struct omap_dss_device *dssdev, | |||
1442 | r = buf_used; | 1461 | r = buf_used; |
1443 | 1462 | ||
1444 | err3: | 1463 | err3: |
1445 | dsi_vc_set_max_rx_packet_size(TCH, 1); | 1464 | dsi_vc_set_max_rx_packet_size(td->channel, 1); |
1446 | err2: | 1465 | err2: |
1447 | dsi_bus_unlock(); | 1466 | dsi_bus_unlock(); |
1448 | err1: | 1467 | err1: |
@@ -1468,7 +1487,7 @@ static void taal_esd_work(struct work_struct *work) | |||
1468 | 1487 | ||
1469 | dsi_bus_lock(); | 1488 | dsi_bus_lock(); |
1470 | 1489 | ||
1471 | r = taal_dcs_read_1(DCS_RDDSDR, &state1); | 1490 | r = taal_dcs_read_1(td, DCS_RDDSDR, &state1); |
1472 | if (r) { | 1491 | if (r) { |
1473 | dev_err(&dssdev->dev, "failed to read Taal status\n"); | 1492 | dev_err(&dssdev->dev, "failed to read Taal status\n"); |
1474 | goto err; | 1493 | goto err; |
@@ -1481,7 +1500,7 @@ static void taal_esd_work(struct work_struct *work) | |||
1481 | goto err; | 1500 | goto err; |
1482 | } | 1501 | } |
1483 | 1502 | ||
1484 | r = taal_dcs_read_1(DCS_RDDSDR, &state2); | 1503 | r = taal_dcs_read_1(td, DCS_RDDSDR, &state2); |
1485 | if (r) { | 1504 | if (r) { |
1486 | dev_err(&dssdev->dev, "failed to read Taal status\n"); | 1505 | dev_err(&dssdev->dev, "failed to read Taal status\n"); |
1487 | goto err; | 1506 | goto err; |
@@ -1497,7 +1516,7 @@ static void taal_esd_work(struct work_struct *work) | |||
1497 | /* Self-diagnostics result is also shown on TE GPIO line. We need | 1516 | /* Self-diagnostics result is also shown on TE GPIO line. We need |
1498 | * to re-enable TE after self diagnostics */ | 1517 | * to re-enable TE after self diagnostics */ |
1499 | if (td->te_enabled && panel_data->use_ext_te) { | 1518 | if (td->te_enabled && panel_data->use_ext_te) { |
1500 | r = taal_dcs_write_1(DCS_TEAR_ON, 0); | 1519 | r = taal_dcs_write_1(td, DCS_TEAR_ON, 0); |
1501 | if (r) | 1520 | if (r) |
1502 | goto err; | 1521 | goto err; |
1503 | } | 1522 | } |
diff --git a/drivers/video/omap2/dss/Kconfig b/drivers/video/omap2/dss/Kconfig index 43b64403eaa4..bfc5da0e9700 100644 --- a/drivers/video/omap2/dss/Kconfig +++ b/drivers/video/omap2/dss/Kconfig | |||
@@ -1,8 +1,8 @@ | |||
1 | menuconfig OMAP2_DSS | 1 | menuconfig OMAP2_DSS |
2 | tristate "OMAP2/3 Display Subsystem support (EXPERIMENTAL)" | 2 | tristate "OMAP2+ Display Subsystem support (EXPERIMENTAL)" |
3 | depends on ARCH_OMAP2 || ARCH_OMAP3 | 3 | depends on ARCH_OMAP2PLUS |
4 | help | 4 | help |
5 | OMAP2/3 Display Subsystem support. | 5 | OMAP2+ Display Subsystem support. |
6 | 6 | ||
7 | if OMAP2_DSS | 7 | if OMAP2_DSS |
8 | 8 | ||
@@ -60,6 +60,14 @@ config OMAP2_DSS_VENC | |||
60 | help | 60 | help |
61 | OMAP Video Encoder support for S-Video and composite TV-out. | 61 | OMAP Video Encoder support for S-Video and composite TV-out. |
62 | 62 | ||
63 | config OMAP4_DSS_HDMI | ||
64 | bool "HDMI support" | ||
65 | depends on ARCH_OMAP4 | ||
66 | default y | ||
67 | help | ||
68 | HDMI Interface. This adds the High Definition Multimedia Interface. | ||
69 | See http://www.hdmi.org/ for HDMI specification. | ||
70 | |||
63 | config OMAP2_DSS_SDI | 71 | config OMAP2_DSS_SDI |
64 | bool "SDI support" | 72 | bool "SDI support" |
65 | depends on ARCH_OMAP3 | 73 | depends on ARCH_OMAP3 |
diff --git a/drivers/video/omap2/dss/Makefile b/drivers/video/omap2/dss/Makefile index 7db17b5e570c..10d9d3bb3e24 100644 --- a/drivers/video/omap2/dss/Makefile +++ b/drivers/video/omap2/dss/Makefile | |||
@@ -5,3 +5,5 @@ omapdss-$(CONFIG_OMAP2_DSS_RFBI) += rfbi.o | |||
5 | omapdss-$(CONFIG_OMAP2_DSS_VENC) += venc.o | 5 | omapdss-$(CONFIG_OMAP2_DSS_VENC) += venc.o |
6 | omapdss-$(CONFIG_OMAP2_DSS_SDI) += sdi.o | 6 | omapdss-$(CONFIG_OMAP2_DSS_SDI) += sdi.o |
7 | omapdss-$(CONFIG_OMAP2_DSS_DSI) += dsi.o | 7 | omapdss-$(CONFIG_OMAP2_DSS_DSI) += dsi.o |
8 | omapdss-$(CONFIG_OMAP4_DSS_HDMI) += hdmi.o \ | ||
9 | hdmi_omap4_panel.o | ||
diff --git a/drivers/video/omap2/dss/core.c b/drivers/video/omap2/dss/core.c index 8e89f6049280..1aa2ed1e786e 100644 --- a/drivers/video/omap2/dss/core.c +++ b/drivers/video/omap2/dss/core.c | |||
@@ -34,332 +34,26 @@ | |||
34 | #include <linux/regulator/consumer.h> | 34 | #include <linux/regulator/consumer.h> |
35 | 35 | ||
36 | #include <plat/display.h> | 36 | #include <plat/display.h> |
37 | #include <plat/clock.h> | ||
38 | 37 | ||
39 | #include "dss.h" | 38 | #include "dss.h" |
40 | #include "dss_features.h" | 39 | #include "dss_features.h" |
41 | 40 | ||
42 | static struct { | 41 | static struct { |
43 | struct platform_device *pdev; | 42 | struct platform_device *pdev; |
44 | int ctx_id; | ||
45 | |||
46 | struct clk *dss_ick; | ||
47 | struct clk *dss1_fck; | ||
48 | struct clk *dss2_fck; | ||
49 | struct clk *dss_54m_fck; | ||
50 | struct clk *dss_96m_fck; | ||
51 | unsigned num_clks_enabled; | ||
52 | 43 | ||
53 | struct regulator *vdds_dsi_reg; | 44 | struct regulator *vdds_dsi_reg; |
54 | struct regulator *vdds_sdi_reg; | 45 | struct regulator *vdds_sdi_reg; |
55 | struct regulator *vdda_dac_reg; | ||
56 | } core; | 46 | } core; |
57 | 47 | ||
58 | static void dss_clk_enable_all_no_ctx(void); | ||
59 | static void dss_clk_disable_all_no_ctx(void); | ||
60 | static void dss_clk_enable_no_ctx(enum dss_clock clks); | ||
61 | static void dss_clk_disable_no_ctx(enum dss_clock clks); | ||
62 | |||
63 | static char *def_disp_name; | 48 | static char *def_disp_name; |
64 | module_param_named(def_disp, def_disp_name, charp, 0); | 49 | module_param_named(def_disp, def_disp_name, charp, 0); |
65 | MODULE_PARM_DESC(def_disp_name, "default display name"); | 50 | MODULE_PARM_DESC(def_disp, "default display name"); |
66 | 51 | ||
67 | #ifdef DEBUG | 52 | #ifdef DEBUG |
68 | unsigned int dss_debug; | 53 | unsigned int dss_debug; |
69 | module_param_named(debug, dss_debug, bool, 0644); | 54 | module_param_named(debug, dss_debug, bool, 0644); |
70 | #endif | 55 | #endif |
71 | 56 | ||
72 | /* CONTEXT */ | ||
73 | static int dss_get_ctx_id(void) | ||
74 | { | ||
75 | struct omap_dss_board_info *pdata = core.pdev->dev.platform_data; | ||
76 | int r; | ||
77 | |||
78 | if (!pdata->get_last_off_on_transaction_id) | ||
79 | return 0; | ||
80 | r = pdata->get_last_off_on_transaction_id(&core.pdev->dev); | ||
81 | if (r < 0) { | ||
82 | dev_err(&core.pdev->dev, "getting transaction ID failed, " | ||
83 | "will force context restore\n"); | ||
84 | r = -1; | ||
85 | } | ||
86 | return r; | ||
87 | } | ||
88 | |||
89 | int dss_need_ctx_restore(void) | ||
90 | { | ||
91 | int id = dss_get_ctx_id(); | ||
92 | |||
93 | if (id < 0 || id != core.ctx_id) { | ||
94 | DSSDBG("ctx id %d -> id %d\n", | ||
95 | core.ctx_id, id); | ||
96 | core.ctx_id = id; | ||
97 | return 1; | ||
98 | } else { | ||
99 | return 0; | ||
100 | } | ||
101 | } | ||
102 | |||
103 | static void save_all_ctx(void) | ||
104 | { | ||
105 | DSSDBG("save context\n"); | ||
106 | |||
107 | dss_clk_enable_no_ctx(DSS_CLK_ICK | DSS_CLK_FCK1); | ||
108 | |||
109 | dss_save_context(); | ||
110 | dispc_save_context(); | ||
111 | #ifdef CONFIG_OMAP2_DSS_DSI | ||
112 | dsi_save_context(); | ||
113 | #endif | ||
114 | |||
115 | dss_clk_disable_no_ctx(DSS_CLK_ICK | DSS_CLK_FCK1); | ||
116 | } | ||
117 | |||
118 | static void restore_all_ctx(void) | ||
119 | { | ||
120 | DSSDBG("restore context\n"); | ||
121 | |||
122 | dss_clk_enable_all_no_ctx(); | ||
123 | |||
124 | dss_restore_context(); | ||
125 | dispc_restore_context(); | ||
126 | #ifdef CONFIG_OMAP2_DSS_DSI | ||
127 | dsi_restore_context(); | ||
128 | #endif | ||
129 | |||
130 | dss_clk_disable_all_no_ctx(); | ||
131 | } | ||
132 | |||
133 | #if defined(CONFIG_DEBUG_FS) && defined(CONFIG_OMAP2_DSS_DEBUG_SUPPORT) | ||
134 | /* CLOCKS */ | ||
135 | static void core_dump_clocks(struct seq_file *s) | ||
136 | { | ||
137 | int i; | ||
138 | struct clk *clocks[5] = { | ||
139 | core.dss_ick, | ||
140 | core.dss1_fck, | ||
141 | core.dss2_fck, | ||
142 | core.dss_54m_fck, | ||
143 | core.dss_96m_fck | ||
144 | }; | ||
145 | |||
146 | seq_printf(s, "- CORE -\n"); | ||
147 | |||
148 | seq_printf(s, "internal clk count\t\t%u\n", core.num_clks_enabled); | ||
149 | |||
150 | for (i = 0; i < 5; i++) { | ||
151 | if (!clocks[i]) | ||
152 | continue; | ||
153 | seq_printf(s, "%-15s\t%lu\t%d\n", | ||
154 | clocks[i]->name, | ||
155 | clk_get_rate(clocks[i]), | ||
156 | clocks[i]->usecount); | ||
157 | } | ||
158 | } | ||
159 | #endif /* defined(CONFIG_DEBUG_FS) && defined(CONFIG_OMAP2_DSS_DEBUG_SUPPORT) */ | ||
160 | |||
161 | static int dss_get_clock(struct clk **clock, const char *clk_name) | ||
162 | { | ||
163 | struct clk *clk; | ||
164 | |||
165 | clk = clk_get(&core.pdev->dev, clk_name); | ||
166 | |||
167 | if (IS_ERR(clk)) { | ||
168 | DSSERR("can't get clock %s", clk_name); | ||
169 | return PTR_ERR(clk); | ||
170 | } | ||
171 | |||
172 | *clock = clk; | ||
173 | |||
174 | DSSDBG("clk %s, rate %ld\n", clk_name, clk_get_rate(clk)); | ||
175 | |||
176 | return 0; | ||
177 | } | ||
178 | |||
179 | static int dss_get_clocks(void) | ||
180 | { | ||
181 | int r; | ||
182 | |||
183 | core.dss_ick = NULL; | ||
184 | core.dss1_fck = NULL; | ||
185 | core.dss2_fck = NULL; | ||
186 | core.dss_54m_fck = NULL; | ||
187 | core.dss_96m_fck = NULL; | ||
188 | |||
189 | r = dss_get_clock(&core.dss_ick, "ick"); | ||
190 | if (r) | ||
191 | goto err; | ||
192 | |||
193 | r = dss_get_clock(&core.dss1_fck, "dss1_fck"); | ||
194 | if (r) | ||
195 | goto err; | ||
196 | |||
197 | r = dss_get_clock(&core.dss2_fck, "dss2_fck"); | ||
198 | if (r) | ||
199 | goto err; | ||
200 | |||
201 | r = dss_get_clock(&core.dss_54m_fck, "tv_fck"); | ||
202 | if (r) | ||
203 | goto err; | ||
204 | |||
205 | r = dss_get_clock(&core.dss_96m_fck, "video_fck"); | ||
206 | if (r) | ||
207 | goto err; | ||
208 | |||
209 | return 0; | ||
210 | |||
211 | err: | ||
212 | if (core.dss_ick) | ||
213 | clk_put(core.dss_ick); | ||
214 | if (core.dss1_fck) | ||
215 | clk_put(core.dss1_fck); | ||
216 | if (core.dss2_fck) | ||
217 | clk_put(core.dss2_fck); | ||
218 | if (core.dss_54m_fck) | ||
219 | clk_put(core.dss_54m_fck); | ||
220 | if (core.dss_96m_fck) | ||
221 | clk_put(core.dss_96m_fck); | ||
222 | |||
223 | return r; | ||
224 | } | ||
225 | |||
226 | static void dss_put_clocks(void) | ||
227 | { | ||
228 | if (core.dss_96m_fck) | ||
229 | clk_put(core.dss_96m_fck); | ||
230 | clk_put(core.dss_54m_fck); | ||
231 | clk_put(core.dss1_fck); | ||
232 | clk_put(core.dss2_fck); | ||
233 | clk_put(core.dss_ick); | ||
234 | } | ||
235 | |||
236 | unsigned long dss_clk_get_rate(enum dss_clock clk) | ||
237 | { | ||
238 | switch (clk) { | ||
239 | case DSS_CLK_ICK: | ||
240 | return clk_get_rate(core.dss_ick); | ||
241 | case DSS_CLK_FCK1: | ||
242 | return clk_get_rate(core.dss1_fck); | ||
243 | case DSS_CLK_FCK2: | ||
244 | return clk_get_rate(core.dss2_fck); | ||
245 | case DSS_CLK_54M: | ||
246 | return clk_get_rate(core.dss_54m_fck); | ||
247 | case DSS_CLK_96M: | ||
248 | return clk_get_rate(core.dss_96m_fck); | ||
249 | } | ||
250 | |||
251 | BUG(); | ||
252 | return 0; | ||
253 | } | ||
254 | |||
255 | static unsigned count_clk_bits(enum dss_clock clks) | ||
256 | { | ||
257 | unsigned num_clks = 0; | ||
258 | |||
259 | if (clks & DSS_CLK_ICK) | ||
260 | ++num_clks; | ||
261 | if (clks & DSS_CLK_FCK1) | ||
262 | ++num_clks; | ||
263 | if (clks & DSS_CLK_FCK2) | ||
264 | ++num_clks; | ||
265 | if (clks & DSS_CLK_54M) | ||
266 | ++num_clks; | ||
267 | if (clks & DSS_CLK_96M) | ||
268 | ++num_clks; | ||
269 | |||
270 | return num_clks; | ||
271 | } | ||
272 | |||
273 | static void dss_clk_enable_no_ctx(enum dss_clock clks) | ||
274 | { | ||
275 | unsigned num_clks = count_clk_bits(clks); | ||
276 | |||
277 | if (clks & DSS_CLK_ICK) | ||
278 | clk_enable(core.dss_ick); | ||
279 | if (clks & DSS_CLK_FCK1) | ||
280 | clk_enable(core.dss1_fck); | ||
281 | if (clks & DSS_CLK_FCK2) | ||
282 | clk_enable(core.dss2_fck); | ||
283 | if (clks & DSS_CLK_54M) | ||
284 | clk_enable(core.dss_54m_fck); | ||
285 | if (clks & DSS_CLK_96M) | ||
286 | clk_enable(core.dss_96m_fck); | ||
287 | |||
288 | core.num_clks_enabled += num_clks; | ||
289 | } | ||
290 | |||
291 | void dss_clk_enable(enum dss_clock clks) | ||
292 | { | ||
293 | bool check_ctx = core.num_clks_enabled == 0; | ||
294 | |||
295 | dss_clk_enable_no_ctx(clks); | ||
296 | |||
297 | if (check_ctx && cpu_is_omap34xx() && dss_need_ctx_restore()) | ||
298 | restore_all_ctx(); | ||
299 | } | ||
300 | |||
301 | static void dss_clk_disable_no_ctx(enum dss_clock clks) | ||
302 | { | ||
303 | unsigned num_clks = count_clk_bits(clks); | ||
304 | |||
305 | if (clks & DSS_CLK_ICK) | ||
306 | clk_disable(core.dss_ick); | ||
307 | if (clks & DSS_CLK_FCK1) | ||
308 | clk_disable(core.dss1_fck); | ||
309 | if (clks & DSS_CLK_FCK2) | ||
310 | clk_disable(core.dss2_fck); | ||
311 | if (clks & DSS_CLK_54M) | ||
312 | clk_disable(core.dss_54m_fck); | ||
313 | if (clks & DSS_CLK_96M) | ||
314 | clk_disable(core.dss_96m_fck); | ||
315 | |||
316 | core.num_clks_enabled -= num_clks; | ||
317 | } | ||
318 | |||
319 | void dss_clk_disable(enum dss_clock clks) | ||
320 | { | ||
321 | if (cpu_is_omap34xx()) { | ||
322 | unsigned num_clks = count_clk_bits(clks); | ||
323 | |||
324 | BUG_ON(core.num_clks_enabled < num_clks); | ||
325 | |||
326 | if (core.num_clks_enabled == num_clks) | ||
327 | save_all_ctx(); | ||
328 | } | ||
329 | |||
330 | dss_clk_disable_no_ctx(clks); | ||
331 | } | ||
332 | |||
333 | static void dss_clk_enable_all_no_ctx(void) | ||
334 | { | ||
335 | enum dss_clock clks; | ||
336 | |||
337 | clks = DSS_CLK_ICK | DSS_CLK_FCK1 | DSS_CLK_FCK2 | DSS_CLK_54M; | ||
338 | if (cpu_is_omap34xx()) | ||
339 | clks |= DSS_CLK_96M; | ||
340 | dss_clk_enable_no_ctx(clks); | ||
341 | } | ||
342 | |||
343 | static void dss_clk_disable_all_no_ctx(void) | ||
344 | { | ||
345 | enum dss_clock clks; | ||
346 | |||
347 | clks = DSS_CLK_ICK | DSS_CLK_FCK1 | DSS_CLK_FCK2 | DSS_CLK_54M; | ||
348 | if (cpu_is_omap34xx()) | ||
349 | clks |= DSS_CLK_96M; | ||
350 | dss_clk_disable_no_ctx(clks); | ||
351 | } | ||
352 | |||
353 | static void dss_clk_disable_all(void) | ||
354 | { | ||
355 | enum dss_clock clks; | ||
356 | |||
357 | clks = DSS_CLK_ICK | DSS_CLK_FCK1 | DSS_CLK_FCK2 | DSS_CLK_54M; | ||
358 | if (cpu_is_omap34xx()) | ||
359 | clks |= DSS_CLK_96M; | ||
360 | dss_clk_disable(clks); | ||
361 | } | ||
362 | |||
363 | /* REGULATORS */ | 57 | /* REGULATORS */ |
364 | 58 | ||
365 | struct regulator *dss_get_vdds_dsi(void) | 59 | struct regulator *dss_get_vdds_dsi(void) |
@@ -390,32 +84,7 @@ struct regulator *dss_get_vdds_sdi(void) | |||
390 | return reg; | 84 | return reg; |
391 | } | 85 | } |
392 | 86 | ||
393 | struct regulator *dss_get_vdda_dac(void) | ||
394 | { | ||
395 | struct regulator *reg; | ||
396 | |||
397 | if (core.vdda_dac_reg != NULL) | ||
398 | return core.vdda_dac_reg; | ||
399 | |||
400 | reg = regulator_get(&core.pdev->dev, "vdda_dac"); | ||
401 | if (!IS_ERR(reg)) | ||
402 | core.vdda_dac_reg = reg; | ||
403 | |||
404 | return reg; | ||
405 | } | ||
406 | |||
407 | /* DEBUGFS */ | ||
408 | #if defined(CONFIG_DEBUG_FS) && defined(CONFIG_OMAP2_DSS_DEBUG_SUPPORT) | 87 | #if defined(CONFIG_DEBUG_FS) && defined(CONFIG_OMAP2_DSS_DEBUG_SUPPORT) |
409 | static void dss_debug_dump_clocks(struct seq_file *s) | ||
410 | { | ||
411 | core_dump_clocks(s); | ||
412 | dss_dump_clocks(s); | ||
413 | dispc_dump_clocks(s); | ||
414 | #ifdef CONFIG_OMAP2_DSS_DSI | ||
415 | dsi_dump_clocks(s); | ||
416 | #endif | ||
417 | } | ||
418 | |||
419 | static int dss_debug_show(struct seq_file *s, void *unused) | 88 | static int dss_debug_show(struct seq_file *s, void *unused) |
420 | { | 89 | { |
421 | void (*func)(struct seq_file *) = s->private; | 90 | void (*func)(struct seq_file *) = s->private; |
@@ -497,7 +166,6 @@ static inline void dss_uninitialize_debugfs(void) | |||
497 | static int omap_dss_probe(struct platform_device *pdev) | 166 | static int omap_dss_probe(struct platform_device *pdev) |
498 | { | 167 | { |
499 | struct omap_dss_board_info *pdata = pdev->dev.platform_data; | 168 | struct omap_dss_board_info *pdata = pdev->dev.platform_data; |
500 | int skip_init = 0; | ||
501 | int r; | 169 | int r; |
502 | int i; | 170 | int i; |
503 | 171 | ||
@@ -508,63 +176,43 @@ static int omap_dss_probe(struct platform_device *pdev) | |||
508 | dss_init_overlay_managers(pdev); | 176 | dss_init_overlay_managers(pdev); |
509 | dss_init_overlays(pdev); | 177 | dss_init_overlays(pdev); |
510 | 178 | ||
511 | r = dss_get_clocks(); | 179 | r = dss_init_platform_driver(); |
512 | if (r) | ||
513 | goto err_clocks; | ||
514 | |||
515 | dss_clk_enable_all_no_ctx(); | ||
516 | |||
517 | core.ctx_id = dss_get_ctx_id(); | ||
518 | DSSDBG("initial ctx id %u\n", core.ctx_id); | ||
519 | |||
520 | #ifdef CONFIG_FB_OMAP_BOOTLOADER_INIT | ||
521 | /* DISPC_CONTROL */ | ||
522 | if (omap_readl(0x48050440) & 1) /* LCD enabled? */ | ||
523 | skip_init = 1; | ||
524 | #endif | ||
525 | |||
526 | r = dss_init(skip_init); | ||
527 | if (r) { | 180 | if (r) { |
528 | DSSERR("Failed to initialize DSS\n"); | 181 | DSSERR("Failed to initialize DSS platform driver\n"); |
529 | goto err_dss; | 182 | goto err_dss; |
530 | } | 183 | } |
531 | 184 | ||
532 | r = rfbi_init(); | 185 | /* keep clocks enabled to prevent context saves/restores during init */ |
533 | if (r) { | 186 | dss_clk_enable(DSS_CLK_ICK | DSS_CLK_FCK); |
534 | DSSERR("Failed to initialize rfbi\n"); | ||
535 | goto err_rfbi; | ||
536 | } | ||
537 | 187 | ||
538 | r = dpi_init(pdev); | 188 | r = rfbi_init_platform_driver(); |
539 | if (r) { | 189 | if (r) { |
540 | DSSERR("Failed to initialize dpi\n"); | 190 | DSSERR("Failed to initialize rfbi platform driver\n"); |
541 | goto err_dpi; | 191 | goto err_rfbi; |
542 | } | 192 | } |
543 | 193 | ||
544 | r = dispc_init(); | 194 | r = dispc_init_platform_driver(); |
545 | if (r) { | 195 | if (r) { |
546 | DSSERR("Failed to initialize dispc\n"); | 196 | DSSERR("Failed to initialize dispc platform driver\n"); |
547 | goto err_dispc; | 197 | goto err_dispc; |
548 | } | 198 | } |
549 | 199 | ||
550 | r = venc_init(pdev); | 200 | r = venc_init_platform_driver(); |
551 | if (r) { | 201 | if (r) { |
552 | DSSERR("Failed to initialize venc\n"); | 202 | DSSERR("Failed to initialize venc platform driver\n"); |
553 | goto err_venc; | 203 | goto err_venc; |
554 | } | 204 | } |
555 | 205 | ||
556 | if (cpu_is_omap34xx()) { | 206 | r = dsi_init_platform_driver(); |
557 | r = sdi_init(skip_init); | 207 | if (r) { |
558 | if (r) { | 208 | DSSERR("Failed to initialize DSI platform driver\n"); |
559 | DSSERR("Failed to initialize SDI\n"); | 209 | goto err_dsi; |
560 | goto err_sdi; | 210 | } |
561 | } | ||
562 | 211 | ||
563 | r = dsi_init(pdev); | 212 | r = hdmi_init_platform_driver(); |
564 | if (r) { | 213 | if (r) { |
565 | DSSERR("Failed to initialize DSI\n"); | 214 | DSSERR("Failed to initialize hdmi\n"); |
566 | goto err_dsi; | 215 | goto err_hdmi; |
567 | } | ||
568 | } | 216 | } |
569 | 217 | ||
570 | r = dss_initialize_debugfs(); | 218 | r = dss_initialize_debugfs(); |
@@ -589,32 +237,25 @@ static int omap_dss_probe(struct platform_device *pdev) | |||
589 | pdata->default_device = dssdev; | 237 | pdata->default_device = dssdev; |
590 | } | 238 | } |
591 | 239 | ||
592 | dss_clk_disable_all(); | 240 | dss_clk_disable(DSS_CLK_ICK | DSS_CLK_FCK); |
593 | 241 | ||
594 | return 0; | 242 | return 0; |
595 | 243 | ||
596 | err_register: | 244 | err_register: |
597 | dss_uninitialize_debugfs(); | 245 | dss_uninitialize_debugfs(); |
598 | err_debugfs: | 246 | err_debugfs: |
599 | if (cpu_is_omap34xx()) | 247 | hdmi_uninit_platform_driver(); |
600 | dsi_exit(); | 248 | err_hdmi: |
249 | dsi_uninit_platform_driver(); | ||
601 | err_dsi: | 250 | err_dsi: |
602 | if (cpu_is_omap34xx()) | 251 | venc_uninit_platform_driver(); |
603 | sdi_exit(); | ||
604 | err_sdi: | ||
605 | venc_exit(); | ||
606 | err_venc: | 252 | err_venc: |
607 | dispc_exit(); | 253 | dispc_uninit_platform_driver(); |
608 | err_dispc: | 254 | err_dispc: |
609 | dpi_exit(); | 255 | rfbi_uninit_platform_driver(); |
610 | err_dpi: | ||
611 | rfbi_exit(); | ||
612 | err_rfbi: | 256 | err_rfbi: |
613 | dss_exit(); | 257 | dss_uninit_platform_driver(); |
614 | err_dss: | 258 | err_dss: |
615 | dss_clk_disable_all_no_ctx(); | ||
616 | dss_put_clocks(); | ||
617 | err_clocks: | ||
618 | 259 | ||
619 | return r; | 260 | return r; |
620 | } | 261 | } |
@@ -623,61 +264,15 @@ static int omap_dss_remove(struct platform_device *pdev) | |||
623 | { | 264 | { |
624 | struct omap_dss_board_info *pdata = pdev->dev.platform_data; | 265 | struct omap_dss_board_info *pdata = pdev->dev.platform_data; |
625 | int i; | 266 | int i; |
626 | int c; | ||
627 | 267 | ||
628 | dss_uninitialize_debugfs(); | 268 | dss_uninitialize_debugfs(); |
629 | 269 | ||
630 | venc_exit(); | 270 | venc_uninit_platform_driver(); |
631 | dispc_exit(); | 271 | dispc_uninit_platform_driver(); |
632 | dpi_exit(); | 272 | rfbi_uninit_platform_driver(); |
633 | rfbi_exit(); | 273 | dsi_uninit_platform_driver(); |
634 | if (cpu_is_omap34xx()) { | 274 | hdmi_uninit_platform_driver(); |
635 | dsi_exit(); | 275 | dss_uninit_platform_driver(); |
636 | sdi_exit(); | ||
637 | } | ||
638 | |||
639 | dss_exit(); | ||
640 | |||
641 | /* these should be removed at some point */ | ||
642 | c = core.dss_ick->usecount; | ||
643 | if (c > 0) { | ||
644 | DSSERR("warning: dss_ick usecount %d, disabling\n", c); | ||
645 | while (c-- > 0) | ||
646 | clk_disable(core.dss_ick); | ||
647 | } | ||
648 | |||
649 | c = core.dss1_fck->usecount; | ||
650 | if (c > 0) { | ||
651 | DSSERR("warning: dss1_fck usecount %d, disabling\n", c); | ||
652 | while (c-- > 0) | ||
653 | clk_disable(core.dss1_fck); | ||
654 | } | ||
655 | |||
656 | c = core.dss2_fck->usecount; | ||
657 | if (c > 0) { | ||
658 | DSSERR("warning: dss2_fck usecount %d, disabling\n", c); | ||
659 | while (c-- > 0) | ||
660 | clk_disable(core.dss2_fck); | ||
661 | } | ||
662 | |||
663 | c = core.dss_54m_fck->usecount; | ||
664 | if (c > 0) { | ||
665 | DSSERR("warning: dss_54m_fck usecount %d, disabling\n", c); | ||
666 | while (c-- > 0) | ||
667 | clk_disable(core.dss_54m_fck); | ||
668 | } | ||
669 | |||
670 | if (core.dss_96m_fck) { | ||
671 | c = core.dss_96m_fck->usecount; | ||
672 | if (c > 0) { | ||
673 | DSSERR("warning: dss_96m_fck usecount %d, disabling\n", | ||
674 | c); | ||
675 | while (c-- > 0) | ||
676 | clk_disable(core.dss_96m_fck); | ||
677 | } | ||
678 | } | ||
679 | |||
680 | dss_put_clocks(); | ||
681 | 276 | ||
682 | dss_uninit_overlays(pdev); | 277 | dss_uninit_overlays(pdev); |
683 | dss_uninit_overlay_managers(pdev); | 278 | dss_uninit_overlay_managers(pdev); |
@@ -965,11 +560,6 @@ static void __exit omap_dss_exit(void) | |||
965 | core.vdds_sdi_reg = NULL; | 560 | core.vdds_sdi_reg = NULL; |
966 | } | 561 | } |
967 | 562 | ||
968 | if (core.vdda_dac_reg != NULL) { | ||
969 | regulator_put(core.vdda_dac_reg); | ||
970 | core.vdda_dac_reg = NULL; | ||
971 | } | ||
972 | |||
973 | platform_driver_unregister(&omap_dss_driver); | 563 | platform_driver_unregister(&omap_dss_driver); |
974 | 564 | ||
975 | omap_dss_bus_unregister(); | 565 | omap_dss_bus_unregister(); |
diff --git a/drivers/video/omap2/dss/dispc.c b/drivers/video/omap2/dss/dispc.c index 9f8c69f16e61..7804779c9da1 100644 --- a/drivers/video/omap2/dss/dispc.c +++ b/drivers/video/omap2/dss/dispc.c | |||
@@ -32,6 +32,7 @@ | |||
32 | #include <linux/delay.h> | 32 | #include <linux/delay.h> |
33 | #include <linux/workqueue.h> | 33 | #include <linux/workqueue.h> |
34 | #include <linux/hardirq.h> | 34 | #include <linux/hardirq.h> |
35 | #include <linux/interrupt.h> | ||
35 | 36 | ||
36 | #include <plat/sram.h> | 37 | #include <plat/sram.h> |
37 | #include <plat/clock.h> | 38 | #include <plat/clock.h> |
@@ -42,8 +43,6 @@ | |||
42 | #include "dss_features.h" | 43 | #include "dss_features.h" |
43 | 44 | ||
44 | /* DISPC */ | 45 | /* DISPC */ |
45 | #define DISPC_BASE 0x48050400 | ||
46 | |||
47 | #define DISPC_SZ_REGS SZ_4K | 46 | #define DISPC_SZ_REGS SZ_4K |
48 | 47 | ||
49 | struct dispc_reg { u16 idx; }; | 48 | struct dispc_reg { u16 idx; }; |
@@ -74,7 +73,7 @@ struct dispc_reg { u16 idx; }; | |||
74 | #define DISPC_TIMING_H(ch) DISPC_REG(ch != 2 ? 0x0064 : 0x0400) | 73 | #define DISPC_TIMING_H(ch) DISPC_REG(ch != 2 ? 0x0064 : 0x0400) |
75 | #define DISPC_TIMING_V(ch) DISPC_REG(ch != 2 ? 0x0068 : 0x0404) | 74 | #define DISPC_TIMING_V(ch) DISPC_REG(ch != 2 ? 0x0068 : 0x0404) |
76 | #define DISPC_POL_FREQ(ch) DISPC_REG(ch != 2 ? 0x006C : 0x0408) | 75 | #define DISPC_POL_FREQ(ch) DISPC_REG(ch != 2 ? 0x006C : 0x0408) |
77 | #define DISPC_DIVISOR(ch) DISPC_REG(ch != 2 ? 0x0070 : 0x040C) | 76 | #define DISPC_DIVISORo(ch) DISPC_REG(ch != 2 ? 0x0070 : 0x040C) |
78 | #define DISPC_GLOBAL_ALPHA DISPC_REG(0x0074) | 77 | #define DISPC_GLOBAL_ALPHA DISPC_REG(0x0074) |
79 | #define DISPC_SIZE_DIG DISPC_REG(0x0078) | 78 | #define DISPC_SIZE_DIG DISPC_REG(0x0078) |
80 | #define DISPC_SIZE_LCD(ch) DISPC_REG(ch != 2 ? 0x007C : 0x03CC) | 79 | #define DISPC_SIZE_LCD(ch) DISPC_REG(ch != 2 ? 0x007C : 0x03CC) |
@@ -129,6 +128,7 @@ struct dispc_reg { u16 idx; }; | |||
129 | 128 | ||
130 | #define DISPC_VID_PRELOAD(n) DISPC_REG(0x230 + (n)*0x04) | 129 | #define DISPC_VID_PRELOAD(n) DISPC_REG(0x230 + (n)*0x04) |
131 | 130 | ||
131 | #define DISPC_DIVISOR DISPC_REG(0x0804) | ||
132 | 132 | ||
133 | #define DISPC_IRQ_MASK_ERROR (DISPC_IRQ_GFX_FIFO_UNDERFLOW | \ | 133 | #define DISPC_IRQ_MASK_ERROR (DISPC_IRQ_GFX_FIFO_UNDERFLOW | \ |
134 | DISPC_IRQ_OCP_ERR | \ | 134 | DISPC_IRQ_OCP_ERR | \ |
@@ -178,7 +178,9 @@ struct dispc_irq_stats { | |||
178 | }; | 178 | }; |
179 | 179 | ||
180 | static struct { | 180 | static struct { |
181 | struct platform_device *pdev; | ||
181 | void __iomem *base; | 182 | void __iomem *base; |
183 | int irq; | ||
182 | 184 | ||
183 | u32 fifo_size[3]; | 185 | u32 fifo_size[3]; |
184 | 186 | ||
@@ -230,7 +232,7 @@ void dispc_save_context(void) | |||
230 | SR(TIMING_H(0)); | 232 | SR(TIMING_H(0)); |
231 | SR(TIMING_V(0)); | 233 | SR(TIMING_V(0)); |
232 | SR(POL_FREQ(0)); | 234 | SR(POL_FREQ(0)); |
233 | SR(DIVISOR(0)); | 235 | SR(DIVISORo(0)); |
234 | SR(GLOBAL_ALPHA); | 236 | SR(GLOBAL_ALPHA); |
235 | SR(SIZE_DIG); | 237 | SR(SIZE_DIG); |
236 | SR(SIZE_LCD(0)); | 238 | SR(SIZE_LCD(0)); |
@@ -242,7 +244,7 @@ void dispc_save_context(void) | |||
242 | SR(TIMING_H(2)); | 244 | SR(TIMING_H(2)); |
243 | SR(TIMING_V(2)); | 245 | SR(TIMING_V(2)); |
244 | SR(POL_FREQ(2)); | 246 | SR(POL_FREQ(2)); |
245 | SR(DIVISOR(2)); | 247 | SR(DIVISORo(2)); |
246 | SR(CONFIG2); | 248 | SR(CONFIG2); |
247 | } | 249 | } |
248 | 250 | ||
@@ -373,6 +375,9 @@ void dispc_save_context(void) | |||
373 | SR(VID_FIR_COEF_V(1, 7)); | 375 | SR(VID_FIR_COEF_V(1, 7)); |
374 | 376 | ||
375 | SR(VID_PRELOAD(1)); | 377 | SR(VID_PRELOAD(1)); |
378 | |||
379 | if (dss_has_feature(FEAT_CORE_CLK_DIV)) | ||
380 | SR(DIVISOR); | ||
376 | } | 381 | } |
377 | 382 | ||
378 | void dispc_restore_context(void) | 383 | void dispc_restore_context(void) |
@@ -389,7 +394,7 @@ void dispc_restore_context(void) | |||
389 | RR(TIMING_H(0)); | 394 | RR(TIMING_H(0)); |
390 | RR(TIMING_V(0)); | 395 | RR(TIMING_V(0)); |
391 | RR(POL_FREQ(0)); | 396 | RR(POL_FREQ(0)); |
392 | RR(DIVISOR(0)); | 397 | RR(DIVISORo(0)); |
393 | RR(GLOBAL_ALPHA); | 398 | RR(GLOBAL_ALPHA); |
394 | RR(SIZE_DIG); | 399 | RR(SIZE_DIG); |
395 | RR(SIZE_LCD(0)); | 400 | RR(SIZE_LCD(0)); |
@@ -400,7 +405,7 @@ void dispc_restore_context(void) | |||
400 | RR(TIMING_H(2)); | 405 | RR(TIMING_H(2)); |
401 | RR(TIMING_V(2)); | 406 | RR(TIMING_V(2)); |
402 | RR(POL_FREQ(2)); | 407 | RR(POL_FREQ(2)); |
403 | RR(DIVISOR(2)); | 408 | RR(DIVISORo(2)); |
404 | RR(CONFIG2); | 409 | RR(CONFIG2); |
405 | } | 410 | } |
406 | 411 | ||
@@ -532,6 +537,9 @@ void dispc_restore_context(void) | |||
532 | 537 | ||
533 | RR(VID_PRELOAD(1)); | 538 | RR(VID_PRELOAD(1)); |
534 | 539 | ||
540 | if (dss_has_feature(FEAT_CORE_CLK_DIV)) | ||
541 | RR(DIVISOR); | ||
542 | |||
535 | /* enable last, because LCD & DIGIT enable are here */ | 543 | /* enable last, because LCD & DIGIT enable are here */ |
536 | RR(CONTROL); | 544 | RR(CONTROL); |
537 | if (dss_has_feature(FEAT_MGR_LCD2)) | 545 | if (dss_has_feature(FEAT_MGR_LCD2)) |
@@ -552,9 +560,9 @@ void dispc_restore_context(void) | |||
552 | static inline void enable_clocks(bool enable) | 560 | static inline void enable_clocks(bool enable) |
553 | { | 561 | { |
554 | if (enable) | 562 | if (enable) |
555 | dss_clk_enable(DSS_CLK_ICK | DSS_CLK_FCK1); | 563 | dss_clk_enable(DSS_CLK_ICK | DSS_CLK_FCK); |
556 | else | 564 | else |
557 | dss_clk_disable(DSS_CLK_ICK | DSS_CLK_FCK1); | 565 | dss_clk_disable(DSS_CLK_ICK | DSS_CLK_FCK); |
558 | } | 566 | } |
559 | 567 | ||
560 | bool dispc_go_busy(enum omap_channel channel) | 568 | bool dispc_go_busy(enum omap_channel channel) |
@@ -1000,6 +1008,20 @@ void dispc_set_burst_size(enum omap_plane plane, | |||
1000 | enable_clocks(0); | 1008 | enable_clocks(0); |
1001 | } | 1009 | } |
1002 | 1010 | ||
1011 | void dispc_enable_gamma_table(bool enable) | ||
1012 | { | ||
1013 | /* | ||
1014 | * This is partially implemented to support only disabling of | ||
1015 | * the gamma table. | ||
1016 | */ | ||
1017 | if (enable) { | ||
1018 | DSSWARN("Gamma table enabling for TV not yet supported"); | ||
1019 | return; | ||
1020 | } | ||
1021 | |||
1022 | REG_FLD_MOD(DISPC_CONFIG, enable, 9, 9); | ||
1023 | } | ||
1024 | |||
1003 | static void _dispc_set_vid_color_conv(enum omap_plane plane, bool enable) | 1025 | static void _dispc_set_vid_color_conv(enum omap_plane plane, bool enable) |
1004 | { | 1026 | { |
1005 | u32 val; | 1027 | u32 val; |
@@ -1129,10 +1151,16 @@ static void _dispc_set_vid_accu0(enum omap_plane plane, int haccu, int vaccu) | |||
1129 | u32 val; | 1151 | u32 val; |
1130 | const struct dispc_reg ac0_reg[] = { DISPC_VID_ACCU0(0), | 1152 | const struct dispc_reg ac0_reg[] = { DISPC_VID_ACCU0(0), |
1131 | DISPC_VID_ACCU0(1) }; | 1153 | DISPC_VID_ACCU0(1) }; |
1154 | u8 hor_start, hor_end, vert_start, vert_end; | ||
1132 | 1155 | ||
1133 | BUG_ON(plane == OMAP_DSS_GFX); | 1156 | BUG_ON(plane == OMAP_DSS_GFX); |
1134 | 1157 | ||
1135 | val = FLD_VAL(vaccu, 25, 16) | FLD_VAL(haccu, 9, 0); | 1158 | dss_feat_get_reg_field(FEAT_REG_HORIZONTALACCU, &hor_start, &hor_end); |
1159 | dss_feat_get_reg_field(FEAT_REG_VERTICALACCU, &vert_start, &vert_end); | ||
1160 | |||
1161 | val = FLD_VAL(vaccu, vert_start, vert_end) | | ||
1162 | FLD_VAL(haccu, hor_start, hor_end); | ||
1163 | |||
1136 | dispc_write_reg(ac0_reg[plane-1], val); | 1164 | dispc_write_reg(ac0_reg[plane-1], val); |
1137 | } | 1165 | } |
1138 | 1166 | ||
@@ -1141,10 +1169,16 @@ static void _dispc_set_vid_accu1(enum omap_plane plane, int haccu, int vaccu) | |||
1141 | u32 val; | 1169 | u32 val; |
1142 | const struct dispc_reg ac1_reg[] = { DISPC_VID_ACCU1(0), | 1170 | const struct dispc_reg ac1_reg[] = { DISPC_VID_ACCU1(0), |
1143 | DISPC_VID_ACCU1(1) }; | 1171 | DISPC_VID_ACCU1(1) }; |
1172 | u8 hor_start, hor_end, vert_start, vert_end; | ||
1144 | 1173 | ||
1145 | BUG_ON(plane == OMAP_DSS_GFX); | 1174 | BUG_ON(plane == OMAP_DSS_GFX); |
1146 | 1175 | ||
1147 | val = FLD_VAL(vaccu, 25, 16) | FLD_VAL(haccu, 9, 0); | 1176 | dss_feat_get_reg_field(FEAT_REG_HORIZONTALACCU, &hor_start, &hor_end); |
1177 | dss_feat_get_reg_field(FEAT_REG_VERTICALACCU, &vert_start, &vert_end); | ||
1178 | |||
1179 | val = FLD_VAL(vaccu, vert_start, vert_end) | | ||
1180 | FLD_VAL(haccu, hor_start, hor_end); | ||
1181 | |||
1148 | dispc_write_reg(ac1_reg[plane-1], val); | 1182 | dispc_write_reg(ac1_reg[plane-1], val); |
1149 | } | 1183 | } |
1150 | 1184 | ||
@@ -1182,16 +1216,25 @@ static void _dispc_set_scaling(enum omap_plane plane, | |||
1182 | _dispc_set_fir(plane, fir_hinc, fir_vinc); | 1216 | _dispc_set_fir(plane, fir_hinc, fir_vinc); |
1183 | 1217 | ||
1184 | l = dispc_read_reg(dispc_reg_att[plane]); | 1218 | l = dispc_read_reg(dispc_reg_att[plane]); |
1185 | l &= ~((0x0f << 5) | (0x3 << 21)); | ||
1186 | 1219 | ||
1220 | /* RESIZEENABLE and VERTICALTAPS */ | ||
1221 | l &= ~((0x3 << 5) | (0x1 << 21)); | ||
1187 | l |= fir_hinc ? (1 << 5) : 0; | 1222 | l |= fir_hinc ? (1 << 5) : 0; |
1188 | l |= fir_vinc ? (1 << 6) : 0; | 1223 | l |= fir_vinc ? (1 << 6) : 0; |
1224 | l |= five_taps ? (1 << 21) : 0; | ||
1189 | 1225 | ||
1190 | l |= hscaleup ? 0 : (1 << 7); | 1226 | /* VRESIZECONF and HRESIZECONF */ |
1191 | l |= vscaleup ? 0 : (1 << 8); | 1227 | if (dss_has_feature(FEAT_RESIZECONF)) { |
1228 | l &= ~(0x3 << 7); | ||
1229 | l |= hscaleup ? 0 : (1 << 7); | ||
1230 | l |= vscaleup ? 0 : (1 << 8); | ||
1231 | } | ||
1192 | 1232 | ||
1193 | l |= five_taps ? (1 << 21) : 0; | 1233 | /* LINEBUFFERSPLIT */ |
1194 | l |= five_taps ? (1 << 22) : 0; | 1234 | if (dss_has_feature(FEAT_LINEBUFFERSPLIT)) { |
1235 | l &= ~(0x1 << 22); | ||
1236 | l |= five_taps ? (1 << 22) : 0; | ||
1237 | } | ||
1195 | 1238 | ||
1196 | dispc_write_reg(dispc_reg_att[plane], l); | 1239 | dispc_write_reg(dispc_reg_att[plane], l); |
1197 | 1240 | ||
@@ -1215,9 +1258,11 @@ static void _dispc_set_scaling(enum omap_plane plane, | |||
1215 | static void _dispc_set_rotation_attrs(enum omap_plane plane, u8 rotation, | 1258 | static void _dispc_set_rotation_attrs(enum omap_plane plane, u8 rotation, |
1216 | bool mirroring, enum omap_color_mode color_mode) | 1259 | bool mirroring, enum omap_color_mode color_mode) |
1217 | { | 1260 | { |
1261 | bool row_repeat = false; | ||
1262 | int vidrot = 0; | ||
1263 | |||
1218 | if (color_mode == OMAP_DSS_COLOR_YUV2 || | 1264 | if (color_mode == OMAP_DSS_COLOR_YUV2 || |
1219 | color_mode == OMAP_DSS_COLOR_UYVY) { | 1265 | color_mode == OMAP_DSS_COLOR_UYVY) { |
1220 | int vidrot = 0; | ||
1221 | 1266 | ||
1222 | if (mirroring) { | 1267 | if (mirroring) { |
1223 | switch (rotation) { | 1268 | switch (rotation) { |
@@ -1251,16 +1296,15 @@ static void _dispc_set_rotation_attrs(enum omap_plane plane, u8 rotation, | |||
1251 | } | 1296 | } |
1252 | } | 1297 | } |
1253 | 1298 | ||
1254 | REG_FLD_MOD(dispc_reg_att[plane], vidrot, 13, 12); | ||
1255 | |||
1256 | if (rotation == OMAP_DSS_ROT_90 || rotation == OMAP_DSS_ROT_270) | 1299 | if (rotation == OMAP_DSS_ROT_90 || rotation == OMAP_DSS_ROT_270) |
1257 | REG_FLD_MOD(dispc_reg_att[plane], 0x1, 18, 18); | 1300 | row_repeat = true; |
1258 | else | 1301 | else |
1259 | REG_FLD_MOD(dispc_reg_att[plane], 0x0, 18, 18); | 1302 | row_repeat = false; |
1260 | } else { | ||
1261 | REG_FLD_MOD(dispc_reg_att[plane], 0, 13, 12); | ||
1262 | REG_FLD_MOD(dispc_reg_att[plane], 0, 18, 18); | ||
1263 | } | 1303 | } |
1304 | |||
1305 | REG_FLD_MOD(dispc_reg_att[plane], vidrot, 13, 12); | ||
1306 | if (dss_has_feature(FEAT_ROWREPEATENABLE)) | ||
1307 | REG_FLD_MOD(dispc_reg_att[plane], row_repeat ? 1 : 0, 18, 18); | ||
1264 | } | 1308 | } |
1265 | 1309 | ||
1266 | static int color_mode_to_bpp(enum omap_color_mode color_mode) | 1310 | static int color_mode_to_bpp(enum omap_color_mode color_mode) |
@@ -2293,7 +2337,7 @@ static void dispc_set_lcd_divisor(enum omap_channel channel, u16 lck_div, | |||
2293 | BUG_ON(pck_div < 2); | 2337 | BUG_ON(pck_div < 2); |
2294 | 2338 | ||
2295 | enable_clocks(1); | 2339 | enable_clocks(1); |
2296 | dispc_write_reg(DISPC_DIVISOR(channel), | 2340 | dispc_write_reg(DISPC_DIVISORo(channel), |
2297 | FLD_VAL(lck_div, 23, 16) | FLD_VAL(pck_div, 7, 0)); | 2341 | FLD_VAL(lck_div, 23, 16) | FLD_VAL(pck_div, 7, 0)); |
2298 | enable_clocks(0); | 2342 | enable_clocks(0); |
2299 | } | 2343 | } |
@@ -2302,7 +2346,7 @@ static void dispc_get_lcd_divisor(enum omap_channel channel, int *lck_div, | |||
2302 | int *pck_div) | 2346 | int *pck_div) |
2303 | { | 2347 | { |
2304 | u32 l; | 2348 | u32 l; |
2305 | l = dispc_read_reg(DISPC_DIVISOR(channel)); | 2349 | l = dispc_read_reg(DISPC_DIVISORo(channel)); |
2306 | *lck_div = FLD_GET(l, 23, 16); | 2350 | *lck_div = FLD_GET(l, 23, 16); |
2307 | *pck_div = FLD_GET(l, 7, 0); | 2351 | *pck_div = FLD_GET(l, 7, 0); |
2308 | } | 2352 | } |
@@ -2311,14 +2355,17 @@ unsigned long dispc_fclk_rate(void) | |||
2311 | { | 2355 | { |
2312 | unsigned long r = 0; | 2356 | unsigned long r = 0; |
2313 | 2357 | ||
2314 | if (dss_get_dispc_clk_source() == DSS_SRC_DSS1_ALWON_FCLK) | 2358 | switch (dss_get_dispc_clk_source()) { |
2315 | r = dss_clk_get_rate(DSS_CLK_FCK1); | 2359 | case DSS_CLK_SRC_FCK: |
2316 | else | 2360 | r = dss_clk_get_rate(DSS_CLK_FCK); |
2317 | #ifdef CONFIG_OMAP2_DSS_DSI | 2361 | break; |
2318 | r = dsi_get_dsi1_pll_rate(); | 2362 | case DSS_CLK_SRC_DSI_PLL_HSDIV_DISPC: |
2319 | #else | 2363 | r = dsi_get_pll_hsdiv_dispc_rate(); |
2320 | BUG(); | 2364 | break; |
2321 | #endif | 2365 | default: |
2366 | BUG(); | ||
2367 | } | ||
2368 | |||
2322 | return r; | 2369 | return r; |
2323 | } | 2370 | } |
2324 | 2371 | ||
@@ -2328,47 +2375,72 @@ unsigned long dispc_lclk_rate(enum omap_channel channel) | |||
2328 | unsigned long r; | 2375 | unsigned long r; |
2329 | u32 l; | 2376 | u32 l; |
2330 | 2377 | ||
2331 | l = dispc_read_reg(DISPC_DIVISOR(channel)); | 2378 | l = dispc_read_reg(DISPC_DIVISORo(channel)); |
2332 | 2379 | ||
2333 | lcd = FLD_GET(l, 23, 16); | 2380 | lcd = FLD_GET(l, 23, 16); |
2334 | 2381 | ||
2335 | r = dispc_fclk_rate(); | 2382 | switch (dss_get_lcd_clk_source(channel)) { |
2383 | case DSS_CLK_SRC_FCK: | ||
2384 | r = dss_clk_get_rate(DSS_CLK_FCK); | ||
2385 | break; | ||
2386 | case DSS_CLK_SRC_DSI_PLL_HSDIV_DISPC: | ||
2387 | r = dsi_get_pll_hsdiv_dispc_rate(); | ||
2388 | break; | ||
2389 | default: | ||
2390 | BUG(); | ||
2391 | } | ||
2336 | 2392 | ||
2337 | return r / lcd; | 2393 | return r / lcd; |
2338 | } | 2394 | } |
2339 | 2395 | ||
2340 | unsigned long dispc_pclk_rate(enum omap_channel channel) | 2396 | unsigned long dispc_pclk_rate(enum omap_channel channel) |
2341 | { | 2397 | { |
2342 | int lcd, pcd; | 2398 | int pcd; |
2343 | unsigned long r; | 2399 | unsigned long r; |
2344 | u32 l; | 2400 | u32 l; |
2345 | 2401 | ||
2346 | l = dispc_read_reg(DISPC_DIVISOR(channel)); | 2402 | l = dispc_read_reg(DISPC_DIVISORo(channel)); |
2347 | 2403 | ||
2348 | lcd = FLD_GET(l, 23, 16); | ||
2349 | pcd = FLD_GET(l, 7, 0); | 2404 | pcd = FLD_GET(l, 7, 0); |
2350 | 2405 | ||
2351 | r = dispc_fclk_rate(); | 2406 | r = dispc_lclk_rate(channel); |
2352 | 2407 | ||
2353 | return r / lcd / pcd; | 2408 | return r / pcd; |
2354 | } | 2409 | } |
2355 | 2410 | ||
2356 | void dispc_dump_clocks(struct seq_file *s) | 2411 | void dispc_dump_clocks(struct seq_file *s) |
2357 | { | 2412 | { |
2358 | int lcd, pcd; | 2413 | int lcd, pcd; |
2414 | u32 l; | ||
2415 | enum dss_clk_source dispc_clk_src = dss_get_dispc_clk_source(); | ||
2416 | enum dss_clk_source lcd_clk_src; | ||
2359 | 2417 | ||
2360 | enable_clocks(1); | 2418 | enable_clocks(1); |
2361 | 2419 | ||
2362 | seq_printf(s, "- DISPC -\n"); | 2420 | seq_printf(s, "- DISPC -\n"); |
2363 | 2421 | ||
2364 | seq_printf(s, "dispc fclk source = %s\n", | 2422 | seq_printf(s, "dispc fclk source = %s (%s)\n", |
2365 | dss_get_dispc_clk_source() == DSS_SRC_DSS1_ALWON_FCLK ? | 2423 | dss_get_generic_clk_source_name(dispc_clk_src), |
2366 | "dss1_alwon_fclk" : "dsi1_pll_fclk"); | 2424 | dss_feat_get_clk_source_name(dispc_clk_src)); |
2367 | 2425 | ||
2368 | seq_printf(s, "fck\t\t%-16lu\n", dispc_fclk_rate()); | 2426 | seq_printf(s, "fck\t\t%-16lu\n", dispc_fclk_rate()); |
2369 | 2427 | ||
2428 | if (dss_has_feature(FEAT_CORE_CLK_DIV)) { | ||
2429 | seq_printf(s, "- DISPC-CORE-CLK -\n"); | ||
2430 | l = dispc_read_reg(DISPC_DIVISOR); | ||
2431 | lcd = FLD_GET(l, 23, 16); | ||
2432 | |||
2433 | seq_printf(s, "lck\t\t%-16lulck div\t%u\n", | ||
2434 | (dispc_fclk_rate()/lcd), lcd); | ||
2435 | } | ||
2370 | seq_printf(s, "- LCD1 -\n"); | 2436 | seq_printf(s, "- LCD1 -\n"); |
2371 | 2437 | ||
2438 | lcd_clk_src = dss_get_lcd_clk_source(OMAP_DSS_CHANNEL_LCD); | ||
2439 | |||
2440 | seq_printf(s, "lcd1_clk source = %s (%s)\n", | ||
2441 | dss_get_generic_clk_source_name(lcd_clk_src), | ||
2442 | dss_feat_get_clk_source_name(lcd_clk_src)); | ||
2443 | |||
2372 | dispc_get_lcd_divisor(OMAP_DSS_CHANNEL_LCD, &lcd, &pcd); | 2444 | dispc_get_lcd_divisor(OMAP_DSS_CHANNEL_LCD, &lcd, &pcd); |
2373 | 2445 | ||
2374 | seq_printf(s, "lck\t\t%-16lulck div\t%u\n", | 2446 | seq_printf(s, "lck\t\t%-16lulck div\t%u\n", |
@@ -2378,6 +2450,12 @@ void dispc_dump_clocks(struct seq_file *s) | |||
2378 | if (dss_has_feature(FEAT_MGR_LCD2)) { | 2450 | if (dss_has_feature(FEAT_MGR_LCD2)) { |
2379 | seq_printf(s, "- LCD2 -\n"); | 2451 | seq_printf(s, "- LCD2 -\n"); |
2380 | 2452 | ||
2453 | lcd_clk_src = dss_get_lcd_clk_source(OMAP_DSS_CHANNEL_LCD2); | ||
2454 | |||
2455 | seq_printf(s, "lcd2_clk source = %s (%s)\n", | ||
2456 | dss_get_generic_clk_source_name(lcd_clk_src), | ||
2457 | dss_feat_get_clk_source_name(lcd_clk_src)); | ||
2458 | |||
2381 | dispc_get_lcd_divisor(OMAP_DSS_CHANNEL_LCD2, &lcd, &pcd); | 2459 | dispc_get_lcd_divisor(OMAP_DSS_CHANNEL_LCD2, &lcd, &pcd); |
2382 | 2460 | ||
2383 | seq_printf(s, "lck\t\t%-16lulck div\t%u\n", | 2461 | seq_printf(s, "lck\t\t%-16lulck div\t%u\n", |
@@ -2440,7 +2518,7 @@ void dispc_dump_regs(struct seq_file *s) | |||
2440 | { | 2518 | { |
2441 | #define DUMPREG(r) seq_printf(s, "%-35s %08x\n", #r, dispc_read_reg(r)) | 2519 | #define DUMPREG(r) seq_printf(s, "%-35s %08x\n", #r, dispc_read_reg(r)) |
2442 | 2520 | ||
2443 | dss_clk_enable(DSS_CLK_ICK | DSS_CLK_FCK1); | 2521 | dss_clk_enable(DSS_CLK_ICK | DSS_CLK_FCK); |
2444 | 2522 | ||
2445 | DUMPREG(DISPC_REVISION); | 2523 | DUMPREG(DISPC_REVISION); |
2446 | DUMPREG(DISPC_SYSCONFIG); | 2524 | DUMPREG(DISPC_SYSCONFIG); |
@@ -2459,7 +2537,7 @@ void dispc_dump_regs(struct seq_file *s) | |||
2459 | DUMPREG(DISPC_TIMING_H(0)); | 2537 | DUMPREG(DISPC_TIMING_H(0)); |
2460 | DUMPREG(DISPC_TIMING_V(0)); | 2538 | DUMPREG(DISPC_TIMING_V(0)); |
2461 | DUMPREG(DISPC_POL_FREQ(0)); | 2539 | DUMPREG(DISPC_POL_FREQ(0)); |
2462 | DUMPREG(DISPC_DIVISOR(0)); | 2540 | DUMPREG(DISPC_DIVISORo(0)); |
2463 | DUMPREG(DISPC_GLOBAL_ALPHA); | 2541 | DUMPREG(DISPC_GLOBAL_ALPHA); |
2464 | DUMPREG(DISPC_SIZE_DIG); | 2542 | DUMPREG(DISPC_SIZE_DIG); |
2465 | DUMPREG(DISPC_SIZE_LCD(0)); | 2543 | DUMPREG(DISPC_SIZE_LCD(0)); |
@@ -2471,7 +2549,7 @@ void dispc_dump_regs(struct seq_file *s) | |||
2471 | DUMPREG(DISPC_TIMING_H(2)); | 2549 | DUMPREG(DISPC_TIMING_H(2)); |
2472 | DUMPREG(DISPC_TIMING_V(2)); | 2550 | DUMPREG(DISPC_TIMING_V(2)); |
2473 | DUMPREG(DISPC_POL_FREQ(2)); | 2551 | DUMPREG(DISPC_POL_FREQ(2)); |
2474 | DUMPREG(DISPC_DIVISOR(2)); | 2552 | DUMPREG(DISPC_DIVISORo(2)); |
2475 | DUMPREG(DISPC_SIZE_LCD(2)); | 2553 | DUMPREG(DISPC_SIZE_LCD(2)); |
2476 | } | 2554 | } |
2477 | 2555 | ||
@@ -2597,7 +2675,7 @@ void dispc_dump_regs(struct seq_file *s) | |||
2597 | DUMPREG(DISPC_VID_PRELOAD(0)); | 2675 | DUMPREG(DISPC_VID_PRELOAD(0)); |
2598 | DUMPREG(DISPC_VID_PRELOAD(1)); | 2676 | DUMPREG(DISPC_VID_PRELOAD(1)); |
2599 | 2677 | ||
2600 | dss_clk_disable(DSS_CLK_ICK | DSS_CLK_FCK1); | 2678 | dss_clk_disable(DSS_CLK_ICK | DSS_CLK_FCK); |
2601 | #undef DUMPREG | 2679 | #undef DUMPREG |
2602 | } | 2680 | } |
2603 | 2681 | ||
@@ -2713,8 +2791,8 @@ int dispc_get_clock_div(enum omap_channel channel, | |||
2713 | 2791 | ||
2714 | fck = dispc_fclk_rate(); | 2792 | fck = dispc_fclk_rate(); |
2715 | 2793 | ||
2716 | cinfo->lck_div = REG_GET(DISPC_DIVISOR(channel), 23, 16); | 2794 | cinfo->lck_div = REG_GET(DISPC_DIVISORo(channel), 23, 16); |
2717 | cinfo->pck_div = REG_GET(DISPC_DIVISOR(channel), 7, 0); | 2795 | cinfo->pck_div = REG_GET(DISPC_DIVISORo(channel), 7, 0); |
2718 | 2796 | ||
2719 | cinfo->lck = fck / cinfo->lck_div; | 2797 | cinfo->lck = fck / cinfo->lck_div; |
2720 | cinfo->pck = cinfo->lck / cinfo->pck_div; | 2798 | cinfo->pck = cinfo->lck / cinfo->pck_div; |
@@ -2791,6 +2869,9 @@ int omap_dispc_register_isr(omap_dispc_isr_t isr, void *arg, u32 mask) | |||
2791 | break; | 2869 | break; |
2792 | } | 2870 | } |
2793 | 2871 | ||
2872 | if (ret) | ||
2873 | goto err; | ||
2874 | |||
2794 | _omap_dispc_set_irqs(); | 2875 | _omap_dispc_set_irqs(); |
2795 | 2876 | ||
2796 | spin_unlock_irqrestore(&dispc.irq_lock, flags); | 2877 | spin_unlock_irqrestore(&dispc.irq_lock, flags); |
@@ -2866,10 +2947,10 @@ static void print_irq_status(u32 status) | |||
2866 | * but we presume they are on because we got an IRQ. However, | 2947 | * but we presume they are on because we got an IRQ. However, |
2867 | * an irq handler may turn the clocks off, so we may not have | 2948 | * an irq handler may turn the clocks off, so we may not have |
2868 | * clock later in the function. */ | 2949 | * clock later in the function. */ |
2869 | void dispc_irq_handler(void) | 2950 | static irqreturn_t omap_dispc_irq_handler(int irq, void *arg) |
2870 | { | 2951 | { |
2871 | int i; | 2952 | int i; |
2872 | u32 irqstatus; | 2953 | u32 irqstatus, irqenable; |
2873 | u32 handledirqs = 0; | 2954 | u32 handledirqs = 0; |
2874 | u32 unhandled_errors; | 2955 | u32 unhandled_errors; |
2875 | struct omap_dispc_isr_data *isr_data; | 2956 | struct omap_dispc_isr_data *isr_data; |
@@ -2878,6 +2959,13 @@ void dispc_irq_handler(void) | |||
2878 | spin_lock(&dispc.irq_lock); | 2959 | spin_lock(&dispc.irq_lock); |
2879 | 2960 | ||
2880 | irqstatus = dispc_read_reg(DISPC_IRQSTATUS); | 2961 | irqstatus = dispc_read_reg(DISPC_IRQSTATUS); |
2962 | irqenable = dispc_read_reg(DISPC_IRQENABLE); | ||
2963 | |||
2964 | /* IRQ is not for us */ | ||
2965 | if (!(irqstatus & irqenable)) { | ||
2966 | spin_unlock(&dispc.irq_lock); | ||
2967 | return IRQ_NONE; | ||
2968 | } | ||
2881 | 2969 | ||
2882 | #ifdef CONFIG_OMAP2_DSS_COLLECT_IRQ_STATS | 2970 | #ifdef CONFIG_OMAP2_DSS_COLLECT_IRQ_STATS |
2883 | spin_lock(&dispc.irq_stats_lock); | 2971 | spin_lock(&dispc.irq_stats_lock); |
@@ -2929,6 +3017,8 @@ void dispc_irq_handler(void) | |||
2929 | } | 3017 | } |
2930 | 3018 | ||
2931 | spin_unlock(&dispc.irq_lock); | 3019 | spin_unlock(&dispc.irq_lock); |
3020 | |||
3021 | return IRQ_HANDLED; | ||
2932 | } | 3022 | } |
2933 | 3023 | ||
2934 | static void dispc_error_worker(struct work_struct *work) | 3024 | static void dispc_error_worker(struct work_struct *work) |
@@ -3253,6 +3343,15 @@ static void _omap_dispc_initial_config(void) | |||
3253 | l = FLD_MOD(l, 1, 0, 0); /* AUTOIDLE */ | 3343 | l = FLD_MOD(l, 1, 0, 0); /* AUTOIDLE */ |
3254 | dispc_write_reg(DISPC_SYSCONFIG, l); | 3344 | dispc_write_reg(DISPC_SYSCONFIG, l); |
3255 | 3345 | ||
3346 | /* Exclusively enable DISPC_CORE_CLK and set divider to 1 */ | ||
3347 | if (dss_has_feature(FEAT_CORE_CLK_DIV)) { | ||
3348 | l = dispc_read_reg(DISPC_DIVISOR); | ||
3349 | /* Use DISPC_DIVISOR.LCD, instead of DISPC_DIVISOR1.LCD */ | ||
3350 | l = FLD_MOD(l, 1, 0, 0); | ||
3351 | l = FLD_MOD(l, 1, 23, 16); | ||
3352 | dispc_write_reg(DISPC_DIVISOR, l); | ||
3353 | } | ||
3354 | |||
3256 | /* FUNCGATED */ | 3355 | /* FUNCGATED */ |
3257 | if (dss_has_feature(FEAT_FUNCGATED)) | 3356 | if (dss_has_feature(FEAT_FUNCGATED)) |
3258 | REG_FLD_MOD(DISPC_CONFIG, 1, 9, 9); | 3357 | REG_FLD_MOD(DISPC_CONFIG, 1, 9, 9); |
@@ -3269,47 +3368,6 @@ static void _omap_dispc_initial_config(void) | |||
3269 | dispc_read_plane_fifo_sizes(); | 3368 | dispc_read_plane_fifo_sizes(); |
3270 | } | 3369 | } |
3271 | 3370 | ||
3272 | int dispc_init(void) | ||
3273 | { | ||
3274 | u32 rev; | ||
3275 | |||
3276 | spin_lock_init(&dispc.irq_lock); | ||
3277 | |||
3278 | #ifdef CONFIG_OMAP2_DSS_COLLECT_IRQ_STATS | ||
3279 | spin_lock_init(&dispc.irq_stats_lock); | ||
3280 | dispc.irq_stats.last_reset = jiffies; | ||
3281 | #endif | ||
3282 | |||
3283 | INIT_WORK(&dispc.error_work, dispc_error_worker); | ||
3284 | |||
3285 | dispc.base = ioremap(DISPC_BASE, DISPC_SZ_REGS); | ||
3286 | if (!dispc.base) { | ||
3287 | DSSERR("can't ioremap DISPC\n"); | ||
3288 | return -ENOMEM; | ||
3289 | } | ||
3290 | |||
3291 | enable_clocks(1); | ||
3292 | |||
3293 | _omap_dispc_initial_config(); | ||
3294 | |||
3295 | _omap_dispc_initialize_irq(); | ||
3296 | |||
3297 | dispc_save_context(); | ||
3298 | |||
3299 | rev = dispc_read_reg(DISPC_REVISION); | ||
3300 | printk(KERN_INFO "OMAP DISPC rev %d.%d\n", | ||
3301 | FLD_GET(rev, 7, 4), FLD_GET(rev, 3, 0)); | ||
3302 | |||
3303 | enable_clocks(0); | ||
3304 | |||
3305 | return 0; | ||
3306 | } | ||
3307 | |||
3308 | void dispc_exit(void) | ||
3309 | { | ||
3310 | iounmap(dispc.base); | ||
3311 | } | ||
3312 | |||
3313 | int dispc_enable_plane(enum omap_plane plane, bool enable) | 3371 | int dispc_enable_plane(enum omap_plane plane, bool enable) |
3314 | { | 3372 | { |
3315 | DSSDBG("dispc_enable_plane %d, %d\n", plane, enable); | 3373 | DSSDBG("dispc_enable_plane %d, %d\n", plane, enable); |
@@ -3359,3 +3417,94 @@ int dispc_setup_plane(enum omap_plane plane, | |||
3359 | 3417 | ||
3360 | return r; | 3418 | return r; |
3361 | } | 3419 | } |
3420 | |||
3421 | /* DISPC HW IP initialisation */ | ||
3422 | static int omap_dispchw_probe(struct platform_device *pdev) | ||
3423 | { | ||
3424 | u32 rev; | ||
3425 | int r = 0; | ||
3426 | struct resource *dispc_mem; | ||
3427 | |||
3428 | dispc.pdev = pdev; | ||
3429 | |||
3430 | spin_lock_init(&dispc.irq_lock); | ||
3431 | |||
3432 | #ifdef CONFIG_OMAP2_DSS_COLLECT_IRQ_STATS | ||
3433 | spin_lock_init(&dispc.irq_stats_lock); | ||
3434 | dispc.irq_stats.last_reset = jiffies; | ||
3435 | #endif | ||
3436 | |||
3437 | INIT_WORK(&dispc.error_work, dispc_error_worker); | ||
3438 | |||
3439 | dispc_mem = platform_get_resource(dispc.pdev, IORESOURCE_MEM, 0); | ||
3440 | if (!dispc_mem) { | ||
3441 | DSSERR("can't get IORESOURCE_MEM DISPC\n"); | ||
3442 | r = -EINVAL; | ||
3443 | goto fail0; | ||
3444 | } | ||
3445 | dispc.base = ioremap(dispc_mem->start, resource_size(dispc_mem)); | ||
3446 | if (!dispc.base) { | ||
3447 | DSSERR("can't ioremap DISPC\n"); | ||
3448 | r = -ENOMEM; | ||
3449 | goto fail0; | ||
3450 | } | ||
3451 | dispc.irq = platform_get_irq(dispc.pdev, 0); | ||
3452 | if (dispc.irq < 0) { | ||
3453 | DSSERR("platform_get_irq failed\n"); | ||
3454 | r = -ENODEV; | ||
3455 | goto fail1; | ||
3456 | } | ||
3457 | |||
3458 | r = request_irq(dispc.irq, omap_dispc_irq_handler, IRQF_SHARED, | ||
3459 | "OMAP DISPC", dispc.pdev); | ||
3460 | if (r < 0) { | ||
3461 | DSSERR("request_irq failed\n"); | ||
3462 | goto fail1; | ||
3463 | } | ||
3464 | |||
3465 | enable_clocks(1); | ||
3466 | |||
3467 | _omap_dispc_initial_config(); | ||
3468 | |||
3469 | _omap_dispc_initialize_irq(); | ||
3470 | |||
3471 | dispc_save_context(); | ||
3472 | |||
3473 | rev = dispc_read_reg(DISPC_REVISION); | ||
3474 | dev_dbg(&pdev->dev, "OMAP DISPC rev %d.%d\n", | ||
3475 | FLD_GET(rev, 7, 4), FLD_GET(rev, 3, 0)); | ||
3476 | |||
3477 | enable_clocks(0); | ||
3478 | |||
3479 | return 0; | ||
3480 | fail1: | ||
3481 | iounmap(dispc.base); | ||
3482 | fail0: | ||
3483 | return r; | ||
3484 | } | ||
3485 | |||
3486 | static int omap_dispchw_remove(struct platform_device *pdev) | ||
3487 | { | ||
3488 | free_irq(dispc.irq, dispc.pdev); | ||
3489 | iounmap(dispc.base); | ||
3490 | return 0; | ||
3491 | } | ||
3492 | |||
3493 | static struct platform_driver omap_dispchw_driver = { | ||
3494 | .probe = omap_dispchw_probe, | ||
3495 | .remove = omap_dispchw_remove, | ||
3496 | .driver = { | ||
3497 | .name = "omapdss_dispc", | ||
3498 | .owner = THIS_MODULE, | ||
3499 | }, | ||
3500 | }; | ||
3501 | |||
3502 | int dispc_init_platform_driver(void) | ||
3503 | { | ||
3504 | return platform_driver_register(&omap_dispchw_driver); | ||
3505 | } | ||
3506 | |||
3507 | void dispc_uninit_platform_driver(void) | ||
3508 | { | ||
3509 | return platform_driver_unregister(&omap_dispchw_driver); | ||
3510 | } | ||
diff --git a/drivers/video/omap2/dss/display.c b/drivers/video/omap2/dss/display.c index 22dd7a474f79..a85a6f38b40c 100644 --- a/drivers/video/omap2/dss/display.c +++ b/drivers/video/omap2/dss/display.c | |||
@@ -25,14 +25,11 @@ | |||
25 | #include <linux/kernel.h> | 25 | #include <linux/kernel.h> |
26 | #include <linux/module.h> | 26 | #include <linux/module.h> |
27 | #include <linux/jiffies.h> | 27 | #include <linux/jiffies.h> |
28 | #include <linux/list.h> | ||
29 | #include <linux/platform_device.h> | 28 | #include <linux/platform_device.h> |
30 | 29 | ||
31 | #include <plat/display.h> | 30 | #include <plat/display.h> |
32 | #include "dss.h" | 31 | #include "dss.h" |
33 | 32 | ||
34 | static LIST_HEAD(display_list); | ||
35 | |||
36 | static ssize_t display_enabled_show(struct device *dev, | 33 | static ssize_t display_enabled_show(struct device *dev, |
37 | struct device_attribute *attr, char *buf) | 34 | struct device_attribute *attr, char *buf) |
38 | { | 35 | { |
@@ -345,6 +342,7 @@ int omapdss_default_get_recommended_bpp(struct omap_dss_device *dssdev) | |||
345 | return 16; | 342 | return 16; |
346 | case OMAP_DISPLAY_TYPE_VENC: | 343 | case OMAP_DISPLAY_TYPE_VENC: |
347 | case OMAP_DISPLAY_TYPE_SDI: | 344 | case OMAP_DISPLAY_TYPE_SDI: |
345 | case OMAP_DISPLAY_TYPE_HDMI: | ||
348 | return 24; | 346 | return 24; |
349 | default: | 347 | default: |
350 | BUG(); | 348 | BUG(); |
@@ -371,6 +369,7 @@ bool dss_use_replication(struct omap_dss_device *dssdev, | |||
371 | case OMAP_DISPLAY_TYPE_DPI: | 369 | case OMAP_DISPLAY_TYPE_DPI: |
372 | bpp = dssdev->phy.dpi.data_lines; | 370 | bpp = dssdev->phy.dpi.data_lines; |
373 | break; | 371 | break; |
372 | case OMAP_DISPLAY_TYPE_HDMI: | ||
374 | case OMAP_DISPLAY_TYPE_VENC: | 373 | case OMAP_DISPLAY_TYPE_VENC: |
375 | case OMAP_DISPLAY_TYPE_SDI: | 374 | case OMAP_DISPLAY_TYPE_SDI: |
376 | bpp = 24; | 375 | bpp = 24; |
@@ -396,29 +395,6 @@ void dss_init_device(struct platform_device *pdev, | |||
396 | switch (dssdev->type) { | 395 | switch (dssdev->type) { |
397 | #ifdef CONFIG_OMAP2_DSS_DPI | 396 | #ifdef CONFIG_OMAP2_DSS_DPI |
398 | case OMAP_DISPLAY_TYPE_DPI: | 397 | case OMAP_DISPLAY_TYPE_DPI: |
399 | #endif | ||
400 | #ifdef CONFIG_OMAP2_DSS_RFBI | ||
401 | case OMAP_DISPLAY_TYPE_DBI: | ||
402 | #endif | ||
403 | #ifdef CONFIG_OMAP2_DSS_SDI | ||
404 | case OMAP_DISPLAY_TYPE_SDI: | ||
405 | #endif | ||
406 | #ifdef CONFIG_OMAP2_DSS_DSI | ||
407 | case OMAP_DISPLAY_TYPE_DSI: | ||
408 | #endif | ||
409 | #ifdef CONFIG_OMAP2_DSS_VENC | ||
410 | case OMAP_DISPLAY_TYPE_VENC: | ||
411 | #endif | ||
412 | break; | ||
413 | default: | ||
414 | DSSERR("Support for display '%s' not compiled in.\n", | ||
415 | dssdev->name); | ||
416 | return; | ||
417 | } | ||
418 | |||
419 | switch (dssdev->type) { | ||
420 | #ifdef CONFIG_OMAP2_DSS_DPI | ||
421 | case OMAP_DISPLAY_TYPE_DPI: | ||
422 | r = dpi_init_display(dssdev); | 398 | r = dpi_init_display(dssdev); |
423 | break; | 399 | break; |
424 | #endif | 400 | #endif |
@@ -442,8 +418,13 @@ void dss_init_device(struct platform_device *pdev, | |||
442 | r = dsi_init_display(dssdev); | 418 | r = dsi_init_display(dssdev); |
443 | break; | 419 | break; |
444 | #endif | 420 | #endif |
421 | case OMAP_DISPLAY_TYPE_HDMI: | ||
422 | r = hdmi_init_display(dssdev); | ||
423 | break; | ||
445 | default: | 424 | default: |
446 | BUG(); | 425 | DSSERR("Support for display '%s' not compiled in.\n", |
426 | dssdev->name); | ||
427 | return; | ||
447 | } | 428 | } |
448 | 429 | ||
449 | if (r) { | 430 | if (r) { |
diff --git a/drivers/video/omap2/dss/dpi.c b/drivers/video/omap2/dss/dpi.c index 75fb0a515430..2d3ca4ca4a05 100644 --- a/drivers/video/omap2/dss/dpi.c +++ b/drivers/video/omap2/dss/dpi.c | |||
@@ -57,13 +57,13 @@ static int dpi_set_dsi_clk(struct omap_dss_device *dssdev, bool is_tft, | |||
57 | if (r) | 57 | if (r) |
58 | return r; | 58 | return r; |
59 | 59 | ||
60 | dss_select_dispc_clk_source(DSS_SRC_DSI1_PLL_FCLK); | 60 | dss_select_dispc_clk_source(DSS_CLK_SRC_DSI_PLL_HSDIV_DISPC); |
61 | 61 | ||
62 | r = dispc_set_clock_div(dssdev->manager->id, &dispc_cinfo); | 62 | r = dispc_set_clock_div(dssdev->manager->id, &dispc_cinfo); |
63 | if (r) | 63 | if (r) |
64 | return r; | 64 | return r; |
65 | 65 | ||
66 | *fck = dsi_cinfo.dsi1_pll_fclk; | 66 | *fck = dsi_cinfo.dsi_pll_hsdiv_dispc_clk; |
67 | *lck_div = dispc_cinfo.lck_div; | 67 | *lck_div = dispc_cinfo.lck_div; |
68 | *pck_div = dispc_cinfo.pck_div; | 68 | *pck_div = dispc_cinfo.pck_div; |
69 | 69 | ||
@@ -107,7 +107,7 @@ static int dpi_set_mode(struct omap_dss_device *dssdev) | |||
107 | bool is_tft; | 107 | bool is_tft; |
108 | int r = 0; | 108 | int r = 0; |
109 | 109 | ||
110 | dss_clk_enable(DSS_CLK_ICK | DSS_CLK_FCK1); | 110 | dss_clk_enable(DSS_CLK_ICK | DSS_CLK_FCK); |
111 | 111 | ||
112 | dispc_set_pol_freq(dssdev->manager->id, dssdev->panel.config, | 112 | dispc_set_pol_freq(dssdev->manager->id, dssdev->panel.config, |
113 | dssdev->panel.acbi, dssdev->panel.acb); | 113 | dssdev->panel.acbi, dssdev->panel.acb); |
@@ -137,7 +137,7 @@ static int dpi_set_mode(struct omap_dss_device *dssdev) | |||
137 | dispc_set_lcd_timings(dssdev->manager->id, t); | 137 | dispc_set_lcd_timings(dssdev->manager->id, t); |
138 | 138 | ||
139 | err0: | 139 | err0: |
140 | dss_clk_disable(DSS_CLK_ICK | DSS_CLK_FCK1); | 140 | dss_clk_disable(DSS_CLK_ICK | DSS_CLK_FCK); |
141 | return r; | 141 | return r; |
142 | } | 142 | } |
143 | 143 | ||
@@ -173,14 +173,14 @@ int omapdss_dpi_display_enable(struct omap_dss_device *dssdev) | |||
173 | goto err1; | 173 | goto err1; |
174 | } | 174 | } |
175 | 175 | ||
176 | dss_clk_enable(DSS_CLK_ICK | DSS_CLK_FCK1); | 176 | dss_clk_enable(DSS_CLK_ICK | DSS_CLK_FCK); |
177 | 177 | ||
178 | r = dpi_basic_init(dssdev); | 178 | r = dpi_basic_init(dssdev); |
179 | if (r) | 179 | if (r) |
180 | goto err2; | 180 | goto err2; |
181 | 181 | ||
182 | #ifdef CONFIG_OMAP2_DSS_USE_DSI_PLL | 182 | #ifdef CONFIG_OMAP2_DSS_USE_DSI_PLL |
183 | dss_clk_enable(DSS_CLK_FCK2); | 183 | dss_clk_enable(DSS_CLK_SYSCK); |
184 | r = dsi_pll_init(dssdev, 0, 1); | 184 | r = dsi_pll_init(dssdev, 0, 1); |
185 | if (r) | 185 | if (r) |
186 | goto err3; | 186 | goto err3; |
@@ -199,10 +199,10 @@ err4: | |||
199 | #ifdef CONFIG_OMAP2_DSS_USE_DSI_PLL | 199 | #ifdef CONFIG_OMAP2_DSS_USE_DSI_PLL |
200 | dsi_pll_uninit(); | 200 | dsi_pll_uninit(); |
201 | err3: | 201 | err3: |
202 | dss_clk_disable(DSS_CLK_FCK2); | 202 | dss_clk_disable(DSS_CLK_SYSCK); |
203 | #endif | 203 | #endif |
204 | err2: | 204 | err2: |
205 | dss_clk_disable(DSS_CLK_ICK | DSS_CLK_FCK1); | 205 | dss_clk_disable(DSS_CLK_ICK | DSS_CLK_FCK); |
206 | if (cpu_is_omap34xx()) | 206 | if (cpu_is_omap34xx()) |
207 | regulator_disable(dpi.vdds_dsi_reg); | 207 | regulator_disable(dpi.vdds_dsi_reg); |
208 | err1: | 208 | err1: |
@@ -217,12 +217,12 @@ void omapdss_dpi_display_disable(struct omap_dss_device *dssdev) | |||
217 | dssdev->manager->disable(dssdev->manager); | 217 | dssdev->manager->disable(dssdev->manager); |
218 | 218 | ||
219 | #ifdef CONFIG_OMAP2_DSS_USE_DSI_PLL | 219 | #ifdef CONFIG_OMAP2_DSS_USE_DSI_PLL |
220 | dss_select_dispc_clk_source(DSS_SRC_DSS1_ALWON_FCLK); | 220 | dss_select_dispc_clk_source(DSS_CLK_SRC_FCK); |
221 | dsi_pll_uninit(); | 221 | dsi_pll_uninit(); |
222 | dss_clk_disable(DSS_CLK_FCK2); | 222 | dss_clk_disable(DSS_CLK_SYSCK); |
223 | #endif | 223 | #endif |
224 | 224 | ||
225 | dss_clk_disable(DSS_CLK_ICK | DSS_CLK_FCK1); | 225 | dss_clk_disable(DSS_CLK_ICK | DSS_CLK_FCK); |
226 | 226 | ||
227 | if (cpu_is_omap34xx()) | 227 | if (cpu_is_omap34xx()) |
228 | regulator_disable(dpi.vdds_dsi_reg); | 228 | regulator_disable(dpi.vdds_dsi_reg); |
@@ -271,7 +271,7 @@ int dpi_check_timings(struct omap_dss_device *dssdev, | |||
271 | if (r) | 271 | if (r) |
272 | return r; | 272 | return r; |
273 | 273 | ||
274 | fck = dsi_cinfo.dsi1_pll_fclk; | 274 | fck = dsi_cinfo.dsi_pll_hsdiv_dispc_clk; |
275 | lck_div = dispc_cinfo.lck_div; | 275 | lck_div = dispc_cinfo.lck_div; |
276 | pck_div = dispc_cinfo.pck_div; | 276 | pck_div = dispc_cinfo.pck_div; |
277 | } | 277 | } |
@@ -303,22 +303,27 @@ int dpi_init_display(struct omap_dss_device *dssdev) | |||
303 | { | 303 | { |
304 | DSSDBG("init_display\n"); | 304 | DSSDBG("init_display\n"); |
305 | 305 | ||
306 | return 0; | 306 | if (cpu_is_omap34xx() && dpi.vdds_dsi_reg == NULL) { |
307 | } | 307 | struct regulator *vdds_dsi; |
308 | 308 | ||
309 | int dpi_init(struct platform_device *pdev) | 309 | vdds_dsi = dss_get_vdds_dsi(); |
310 | { | 310 | |
311 | if (cpu_is_omap34xx()) { | 311 | if (IS_ERR(vdds_dsi)) { |
312 | dpi.vdds_dsi_reg = dss_get_vdds_dsi(); | ||
313 | if (IS_ERR(dpi.vdds_dsi_reg)) { | ||
314 | DSSERR("can't get VDDS_DSI regulator\n"); | 312 | DSSERR("can't get VDDS_DSI regulator\n"); |
315 | return PTR_ERR(dpi.vdds_dsi_reg); | 313 | return PTR_ERR(vdds_dsi); |
316 | } | 314 | } |
315 | |||
316 | dpi.vdds_dsi_reg = vdds_dsi; | ||
317 | } | 317 | } |
318 | 318 | ||
319 | return 0; | 319 | return 0; |
320 | } | 320 | } |
321 | 321 | ||
322 | int dpi_init(void) | ||
323 | { | ||
324 | return 0; | ||
325 | } | ||
326 | |||
322 | void dpi_exit(void) | 327 | void dpi_exit(void) |
323 | { | 328 | { |
324 | } | 329 | } |
diff --git a/drivers/video/omap2/dss/dsi.c b/drivers/video/omap2/dss/dsi.c index ddf3a0560822..0a7f1a47f8e3 100644 --- a/drivers/video/omap2/dss/dsi.c +++ b/drivers/video/omap2/dss/dsi.c | |||
@@ -38,12 +38,11 @@ | |||
38 | #include <plat/clock.h> | 38 | #include <plat/clock.h> |
39 | 39 | ||
40 | #include "dss.h" | 40 | #include "dss.h" |
41 | #include "dss_features.h" | ||
41 | 42 | ||
42 | /*#define VERBOSE_IRQ*/ | 43 | /*#define VERBOSE_IRQ*/ |
43 | #define DSI_CATCH_MISSING_TE | 44 | #define DSI_CATCH_MISSING_TE |
44 | 45 | ||
45 | #define DSI_BASE 0x4804FC00 | ||
46 | |||
47 | struct dsi_reg { u16 idx; }; | 46 | struct dsi_reg { u16 idx; }; |
48 | 47 | ||
49 | #define DSI_REG(idx) ((const struct dsi_reg) { idx }) | 48 | #define DSI_REG(idx) ((const struct dsi_reg) { idx }) |
@@ -186,13 +185,15 @@ struct dsi_reg { u16 idx; }; | |||
186 | #define DSI_DT_RX_SHORT_READ_1 0x21 | 185 | #define DSI_DT_RX_SHORT_READ_1 0x21 |
187 | #define DSI_DT_RX_SHORT_READ_2 0x22 | 186 | #define DSI_DT_RX_SHORT_READ_2 0x22 |
188 | 187 | ||
189 | #define FINT_MAX 2100000 | 188 | typedef void (*omap_dsi_isr_t) (void *arg, u32 mask); |
190 | #define FINT_MIN 750000 | 189 | |
191 | #define REGN_MAX (1 << 7) | 190 | #define DSI_MAX_NR_ISRS 2 |
192 | #define REGM_MAX ((1 << 11) - 1) | 191 | |
193 | #define REGM3_MAX (1 << 4) | 192 | struct dsi_isr_data { |
194 | #define REGM4_MAX (1 << 4) | 193 | omap_dsi_isr_t isr; |
195 | #define LP_DIV_MAX ((1 << 13) - 1) | 194 | void *arg; |
195 | u32 mask; | ||
196 | }; | ||
196 | 197 | ||
197 | enum fifo_size { | 198 | enum fifo_size { |
198 | DSI_FIFO_SIZE_0 = 0, | 199 | DSI_FIFO_SIZE_0 = 0, |
@@ -220,9 +221,17 @@ struct dsi_irq_stats { | |||
220 | unsigned cio_irqs[32]; | 221 | unsigned cio_irqs[32]; |
221 | }; | 222 | }; |
222 | 223 | ||
224 | struct dsi_isr_tables { | ||
225 | struct dsi_isr_data isr_table[DSI_MAX_NR_ISRS]; | ||
226 | struct dsi_isr_data isr_table_vc[4][DSI_MAX_NR_ISRS]; | ||
227 | struct dsi_isr_data isr_table_cio[DSI_MAX_NR_ISRS]; | ||
228 | }; | ||
229 | |||
223 | static struct | 230 | static struct |
224 | { | 231 | { |
232 | struct platform_device *pdev; | ||
225 | void __iomem *base; | 233 | void __iomem *base; |
234 | int irq; | ||
226 | 235 | ||
227 | struct dsi_clock_info current_cinfo; | 236 | struct dsi_clock_info current_cinfo; |
228 | 237 | ||
@@ -232,6 +241,7 @@ static struct | |||
232 | enum dsi_vc_mode mode; | 241 | enum dsi_vc_mode mode; |
233 | struct omap_dss_device *dssdev; | 242 | struct omap_dss_device *dssdev; |
234 | enum fifo_size fifo_size; | 243 | enum fifo_size fifo_size; |
244 | int vc_id; | ||
235 | } vc[4]; | 245 | } vc[4]; |
236 | 246 | ||
237 | struct mutex lock; | 247 | struct mutex lock; |
@@ -239,8 +249,10 @@ static struct | |||
239 | 249 | ||
240 | unsigned pll_locked; | 250 | unsigned pll_locked; |
241 | 251 | ||
242 | struct completion bta_completion; | 252 | spinlock_t irq_lock; |
243 | void (*bta_callback)(void); | 253 | struct dsi_isr_tables isr_tables; |
254 | /* space for a copy used by the interrupt handler */ | ||
255 | struct dsi_isr_tables isr_tables_copy; | ||
244 | 256 | ||
245 | int update_channel; | 257 | int update_channel; |
246 | struct dsi_update_region update_region; | 258 | struct dsi_update_region update_region; |
@@ -275,6 +287,11 @@ static struct | |||
275 | spinlock_t irq_stats_lock; | 287 | spinlock_t irq_stats_lock; |
276 | struct dsi_irq_stats irq_stats; | 288 | struct dsi_irq_stats irq_stats; |
277 | #endif | 289 | #endif |
290 | /* DSI PLL Parameter Ranges */ | ||
291 | unsigned long regm_max, regn_max; | ||
292 | unsigned long regm_dispc_max, regm_dsi_max; | ||
293 | unsigned long fint_min, fint_max; | ||
294 | unsigned long lpdiv_max; | ||
278 | } dsi; | 295 | } dsi; |
279 | 296 | ||
280 | #ifdef DEBUG | 297 | #ifdef DEBUG |
@@ -318,6 +335,11 @@ static bool dsi_bus_is_locked(void) | |||
318 | return dsi.bus_lock.count == 0; | 335 | return dsi.bus_lock.count == 0; |
319 | } | 336 | } |
320 | 337 | ||
338 | static void dsi_completion_handler(void *data, u32 mask) | ||
339 | { | ||
340 | complete((struct completion *)data); | ||
341 | } | ||
342 | |||
321 | static inline int wait_for_bit_change(const struct dsi_reg idx, int bitnum, | 343 | static inline int wait_for_bit_change(const struct dsi_reg idx, int bitnum, |
322 | int value) | 344 | int value) |
323 | { | 345 | { |
@@ -387,6 +409,9 @@ static void dsi_perf_show(const char *name) | |||
387 | 409 | ||
388 | static void print_irq_status(u32 status) | 410 | static void print_irq_status(u32 status) |
389 | { | 411 | { |
412 | if (status == 0) | ||
413 | return; | ||
414 | |||
390 | #ifndef VERBOSE_IRQ | 415 | #ifndef VERBOSE_IRQ |
391 | if ((status & ~DSI_IRQ_CHANNEL_MASK) == 0) | 416 | if ((status & ~DSI_IRQ_CHANNEL_MASK) == 0) |
392 | return; | 417 | return; |
@@ -422,6 +447,9 @@ static void print_irq_status(u32 status) | |||
422 | 447 | ||
423 | static void print_irq_status_vc(int channel, u32 status) | 448 | static void print_irq_status_vc(int channel, u32 status) |
424 | { | 449 | { |
450 | if (status == 0) | ||
451 | return; | ||
452 | |||
425 | #ifndef VERBOSE_IRQ | 453 | #ifndef VERBOSE_IRQ |
426 | if ((status & ~DSI_VC_IRQ_PACKET_SENT) == 0) | 454 | if ((status & ~DSI_VC_IRQ_PACKET_SENT) == 0) |
427 | return; | 455 | return; |
@@ -448,6 +476,9 @@ static void print_irq_status_vc(int channel, u32 status) | |||
448 | 476 | ||
449 | static void print_irq_status_cio(u32 status) | 477 | static void print_irq_status_cio(u32 status) |
450 | { | 478 | { |
479 | if (status == 0) | ||
480 | return; | ||
481 | |||
451 | printk(KERN_DEBUG "DSI CIO IRQ 0x%x: ", status); | 482 | printk(KERN_DEBUG "DSI CIO IRQ 0x%x: ", status); |
452 | 483 | ||
453 | #define PIS(x) \ | 484 | #define PIS(x) \ |
@@ -478,22 +509,33 @@ static void print_irq_status_cio(u32 status) | |||
478 | printk("\n"); | 509 | printk("\n"); |
479 | } | 510 | } |
480 | 511 | ||
481 | static int debug_irq; | 512 | #ifdef CONFIG_OMAP2_DSS_COLLECT_IRQ_STATS |
482 | 513 | static void dsi_collect_irq_stats(u32 irqstatus, u32 *vcstatus, u32 ciostatus) | |
483 | /* called from dss */ | ||
484 | void dsi_irq_handler(void) | ||
485 | { | 514 | { |
486 | u32 irqstatus, vcstatus, ciostatus; | ||
487 | int i; | 515 | int i; |
488 | 516 | ||
489 | irqstatus = dsi_read_reg(DSI_IRQSTATUS); | ||
490 | |||
491 | #ifdef CONFIG_OMAP2_DSS_COLLECT_IRQ_STATS | ||
492 | spin_lock(&dsi.irq_stats_lock); | 517 | spin_lock(&dsi.irq_stats_lock); |
518 | |||
493 | dsi.irq_stats.irq_count++; | 519 | dsi.irq_stats.irq_count++; |
494 | dss_collect_irq_stats(irqstatus, dsi.irq_stats.dsi_irqs); | 520 | dss_collect_irq_stats(irqstatus, dsi.irq_stats.dsi_irqs); |
521 | |||
522 | for (i = 0; i < 4; ++i) | ||
523 | dss_collect_irq_stats(vcstatus[i], dsi.irq_stats.vc_irqs[i]); | ||
524 | |||
525 | dss_collect_irq_stats(ciostatus, dsi.irq_stats.cio_irqs); | ||
526 | |||
527 | spin_unlock(&dsi.irq_stats_lock); | ||
528 | } | ||
529 | #else | ||
530 | #define dsi_collect_irq_stats(irqstatus, vcstatus, ciostatus) | ||
495 | #endif | 531 | #endif |
496 | 532 | ||
533 | static int debug_irq; | ||
534 | |||
535 | static void dsi_handle_irq_errors(u32 irqstatus, u32 *vcstatus, u32 ciostatus) | ||
536 | { | ||
537 | int i; | ||
538 | |||
497 | if (irqstatus & DSI_IRQ_ERROR_MASK) { | 539 | if (irqstatus & DSI_IRQ_ERROR_MASK) { |
498 | DSSERR("DSI error, irqstatus %x\n", irqstatus); | 540 | DSSERR("DSI error, irqstatus %x\n", irqstatus); |
499 | print_irq_status(irqstatus); | 541 | print_irq_status(irqstatus); |
@@ -504,37 +546,88 @@ void dsi_irq_handler(void) | |||
504 | print_irq_status(irqstatus); | 546 | print_irq_status(irqstatus); |
505 | } | 547 | } |
506 | 548 | ||
507 | #ifdef DSI_CATCH_MISSING_TE | 549 | for (i = 0; i < 4; ++i) { |
508 | if (irqstatus & DSI_IRQ_TE_TRIGGER) | 550 | if (vcstatus[i] & DSI_VC_IRQ_ERROR_MASK) { |
509 | del_timer(&dsi.te_timer); | 551 | DSSERR("DSI VC(%d) error, vc irqstatus %x\n", |
510 | #endif | 552 | i, vcstatus[i]); |
553 | print_irq_status_vc(i, vcstatus[i]); | ||
554 | } else if (debug_irq) { | ||
555 | print_irq_status_vc(i, vcstatus[i]); | ||
556 | } | ||
557 | } | ||
558 | |||
559 | if (ciostatus & DSI_CIO_IRQ_ERROR_MASK) { | ||
560 | DSSERR("DSI CIO error, cio irqstatus %x\n", ciostatus); | ||
561 | print_irq_status_cio(ciostatus); | ||
562 | } else if (debug_irq) { | ||
563 | print_irq_status_cio(ciostatus); | ||
564 | } | ||
565 | } | ||
566 | |||
567 | static void dsi_call_isrs(struct dsi_isr_data *isr_array, | ||
568 | unsigned isr_array_size, u32 irqstatus) | ||
569 | { | ||
570 | struct dsi_isr_data *isr_data; | ||
571 | int i; | ||
572 | |||
573 | for (i = 0; i < isr_array_size; i++) { | ||
574 | isr_data = &isr_array[i]; | ||
575 | if (isr_data->isr && isr_data->mask & irqstatus) | ||
576 | isr_data->isr(isr_data->arg, irqstatus); | ||
577 | } | ||
578 | } | ||
579 | |||
580 | static void dsi_handle_isrs(struct dsi_isr_tables *isr_tables, | ||
581 | u32 irqstatus, u32 *vcstatus, u32 ciostatus) | ||
582 | { | ||
583 | int i; | ||
584 | |||
585 | dsi_call_isrs(isr_tables->isr_table, | ||
586 | ARRAY_SIZE(isr_tables->isr_table), | ||
587 | irqstatus); | ||
511 | 588 | ||
512 | for (i = 0; i < 4; ++i) { | 589 | for (i = 0; i < 4; ++i) { |
513 | if ((irqstatus & (1<<i)) == 0) | 590 | if (vcstatus[i] == 0) |
514 | continue; | 591 | continue; |
592 | dsi_call_isrs(isr_tables->isr_table_vc[i], | ||
593 | ARRAY_SIZE(isr_tables->isr_table_vc[i]), | ||
594 | vcstatus[i]); | ||
595 | } | ||
515 | 596 | ||
516 | vcstatus = dsi_read_reg(DSI_VC_IRQSTATUS(i)); | 597 | if (ciostatus != 0) |
598 | dsi_call_isrs(isr_tables->isr_table_cio, | ||
599 | ARRAY_SIZE(isr_tables->isr_table_cio), | ||
600 | ciostatus); | ||
601 | } | ||
517 | 602 | ||
518 | #ifdef CONFIG_OMAP2_DSS_COLLECT_IRQ_STATS | 603 | static irqreturn_t omap_dsi_irq_handler(int irq, void *arg) |
519 | dss_collect_irq_stats(vcstatus, dsi.irq_stats.vc_irqs[i]); | 604 | { |
520 | #endif | 605 | u32 irqstatus, vcstatus[4], ciostatus; |
606 | int i; | ||
521 | 607 | ||
522 | if (vcstatus & DSI_VC_IRQ_BTA) { | 608 | spin_lock(&dsi.irq_lock); |
523 | complete(&dsi.bta_completion); | ||
524 | 609 | ||
525 | if (dsi.bta_callback) | 610 | irqstatus = dsi_read_reg(DSI_IRQSTATUS); |
526 | dsi.bta_callback(); | ||
527 | } | ||
528 | 611 | ||
529 | if (vcstatus & DSI_VC_IRQ_ERROR_MASK) { | 612 | /* IRQ is not for us */ |
530 | DSSERR("DSI VC(%d) error, vc irqstatus %x\n", | 613 | if (!irqstatus) { |
531 | i, vcstatus); | 614 | spin_unlock(&dsi.irq_lock); |
532 | print_irq_status_vc(i, vcstatus); | 615 | return IRQ_NONE; |
533 | } else if (debug_irq) { | 616 | } |
534 | print_irq_status_vc(i, vcstatus); | 617 | |
618 | dsi_write_reg(DSI_IRQSTATUS, irqstatus & ~DSI_IRQ_CHANNEL_MASK); | ||
619 | /* flush posted write */ | ||
620 | dsi_read_reg(DSI_IRQSTATUS); | ||
621 | |||
622 | for (i = 0; i < 4; ++i) { | ||
623 | if ((irqstatus & (1 << i)) == 0) { | ||
624 | vcstatus[i] = 0; | ||
625 | continue; | ||
535 | } | 626 | } |
536 | 627 | ||
537 | dsi_write_reg(DSI_VC_IRQSTATUS(i), vcstatus); | 628 | vcstatus[i] = dsi_read_reg(DSI_VC_IRQSTATUS(i)); |
629 | |||
630 | dsi_write_reg(DSI_VC_IRQSTATUS(i), vcstatus[i]); | ||
538 | /* flush posted write */ | 631 | /* flush posted write */ |
539 | dsi_read_reg(DSI_VC_IRQSTATUS(i)); | 632 | dsi_read_reg(DSI_VC_IRQSTATUS(i)); |
540 | } | 633 | } |
@@ -542,117 +635,307 @@ void dsi_irq_handler(void) | |||
542 | if (irqstatus & DSI_IRQ_COMPLEXIO_ERR) { | 635 | if (irqstatus & DSI_IRQ_COMPLEXIO_ERR) { |
543 | ciostatus = dsi_read_reg(DSI_COMPLEXIO_IRQ_STATUS); | 636 | ciostatus = dsi_read_reg(DSI_COMPLEXIO_IRQ_STATUS); |
544 | 637 | ||
545 | #ifdef CONFIG_OMAP2_DSS_COLLECT_IRQ_STATS | ||
546 | dss_collect_irq_stats(ciostatus, dsi.irq_stats.cio_irqs); | ||
547 | #endif | ||
548 | |||
549 | dsi_write_reg(DSI_COMPLEXIO_IRQ_STATUS, ciostatus); | 638 | dsi_write_reg(DSI_COMPLEXIO_IRQ_STATUS, ciostatus); |
550 | /* flush posted write */ | 639 | /* flush posted write */ |
551 | dsi_read_reg(DSI_COMPLEXIO_IRQ_STATUS); | 640 | dsi_read_reg(DSI_COMPLEXIO_IRQ_STATUS); |
641 | } else { | ||
642 | ciostatus = 0; | ||
643 | } | ||
552 | 644 | ||
553 | if (ciostatus & DSI_CIO_IRQ_ERROR_MASK) { | 645 | #ifdef DSI_CATCH_MISSING_TE |
554 | DSSERR("DSI CIO error, cio irqstatus %x\n", ciostatus); | 646 | if (irqstatus & DSI_IRQ_TE_TRIGGER) |
555 | print_irq_status_cio(ciostatus); | 647 | del_timer(&dsi.te_timer); |
556 | } else if (debug_irq) { | 648 | #endif |
557 | print_irq_status_cio(ciostatus); | 649 | |
558 | } | 650 | /* make a copy and unlock, so that isrs can unregister |
651 | * themselves */ | ||
652 | memcpy(&dsi.isr_tables_copy, &dsi.isr_tables, sizeof(dsi.isr_tables)); | ||
653 | |||
654 | spin_unlock(&dsi.irq_lock); | ||
655 | |||
656 | dsi_handle_isrs(&dsi.isr_tables_copy, irqstatus, vcstatus, ciostatus); | ||
657 | |||
658 | dsi_handle_irq_errors(irqstatus, vcstatus, ciostatus); | ||
659 | |||
660 | dsi_collect_irq_stats(irqstatus, vcstatus, ciostatus); | ||
661 | |||
662 | return IRQ_HANDLED; | ||
663 | } | ||
664 | |||
665 | /* dsi.irq_lock has to be locked by the caller */ | ||
666 | static void _omap_dsi_configure_irqs(struct dsi_isr_data *isr_array, | ||
667 | unsigned isr_array_size, u32 default_mask, | ||
668 | const struct dsi_reg enable_reg, | ||
669 | const struct dsi_reg status_reg) | ||
670 | { | ||
671 | struct dsi_isr_data *isr_data; | ||
672 | u32 mask; | ||
673 | u32 old_mask; | ||
674 | int i; | ||
675 | |||
676 | mask = default_mask; | ||
677 | |||
678 | for (i = 0; i < isr_array_size; i++) { | ||
679 | isr_data = &isr_array[i]; | ||
680 | |||
681 | if (isr_data->isr == NULL) | ||
682 | continue; | ||
683 | |||
684 | mask |= isr_data->mask; | ||
559 | } | 685 | } |
560 | 686 | ||
561 | dsi_write_reg(DSI_IRQSTATUS, irqstatus & ~DSI_IRQ_CHANNEL_MASK); | 687 | old_mask = dsi_read_reg(enable_reg); |
562 | /* flush posted write */ | 688 | /* clear the irqstatus for newly enabled irqs */ |
563 | dsi_read_reg(DSI_IRQSTATUS); | 689 | dsi_write_reg(status_reg, (mask ^ old_mask) & mask); |
690 | dsi_write_reg(enable_reg, mask); | ||
564 | 691 | ||
565 | #ifdef CONFIG_OMAP2_DSS_COLLECT_IRQ_STATS | 692 | /* flush posted writes */ |
566 | spin_unlock(&dsi.irq_stats_lock); | 693 | dsi_read_reg(enable_reg); |
694 | dsi_read_reg(status_reg); | ||
695 | } | ||
696 | |||
697 | /* dsi.irq_lock has to be locked by the caller */ | ||
698 | static void _omap_dsi_set_irqs(void) | ||
699 | { | ||
700 | u32 mask = DSI_IRQ_ERROR_MASK; | ||
701 | #ifdef DSI_CATCH_MISSING_TE | ||
702 | mask |= DSI_IRQ_TE_TRIGGER; | ||
567 | #endif | 703 | #endif |
704 | _omap_dsi_configure_irqs(dsi.isr_tables.isr_table, | ||
705 | ARRAY_SIZE(dsi.isr_tables.isr_table), mask, | ||
706 | DSI_IRQENABLE, DSI_IRQSTATUS); | ||
707 | } | ||
708 | |||
709 | /* dsi.irq_lock has to be locked by the caller */ | ||
710 | static void _omap_dsi_set_irqs_vc(int vc) | ||
711 | { | ||
712 | _omap_dsi_configure_irqs(dsi.isr_tables.isr_table_vc[vc], | ||
713 | ARRAY_SIZE(dsi.isr_tables.isr_table_vc[vc]), | ||
714 | DSI_VC_IRQ_ERROR_MASK, | ||
715 | DSI_VC_IRQENABLE(vc), DSI_VC_IRQSTATUS(vc)); | ||
568 | } | 716 | } |
569 | 717 | ||
718 | /* dsi.irq_lock has to be locked by the caller */ | ||
719 | static void _omap_dsi_set_irqs_cio(void) | ||
720 | { | ||
721 | _omap_dsi_configure_irqs(dsi.isr_tables.isr_table_cio, | ||
722 | ARRAY_SIZE(dsi.isr_tables.isr_table_cio), | ||
723 | DSI_CIO_IRQ_ERROR_MASK, | ||
724 | DSI_COMPLEXIO_IRQ_ENABLE, DSI_COMPLEXIO_IRQ_STATUS); | ||
725 | } | ||
570 | 726 | ||
571 | static void _dsi_initialize_irq(void) | 727 | static void _dsi_initialize_irq(void) |
572 | { | 728 | { |
573 | u32 l; | 729 | unsigned long flags; |
730 | int vc; | ||
731 | |||
732 | spin_lock_irqsave(&dsi.irq_lock, flags); | ||
733 | |||
734 | memset(&dsi.isr_tables, 0, sizeof(dsi.isr_tables)); | ||
735 | |||
736 | _omap_dsi_set_irqs(); | ||
737 | for (vc = 0; vc < 4; ++vc) | ||
738 | _omap_dsi_set_irqs_vc(vc); | ||
739 | _omap_dsi_set_irqs_cio(); | ||
740 | |||
741 | spin_unlock_irqrestore(&dsi.irq_lock, flags); | ||
742 | } | ||
743 | |||
744 | static int _dsi_register_isr(omap_dsi_isr_t isr, void *arg, u32 mask, | ||
745 | struct dsi_isr_data *isr_array, unsigned isr_array_size) | ||
746 | { | ||
747 | struct dsi_isr_data *isr_data; | ||
748 | int free_idx; | ||
574 | int i; | 749 | int i; |
575 | 750 | ||
576 | /* disable all interrupts */ | 751 | BUG_ON(isr == NULL); |
577 | dsi_write_reg(DSI_IRQENABLE, 0); | ||
578 | for (i = 0; i < 4; ++i) | ||
579 | dsi_write_reg(DSI_VC_IRQENABLE(i), 0); | ||
580 | dsi_write_reg(DSI_COMPLEXIO_IRQ_ENABLE, 0); | ||
581 | 752 | ||
582 | /* clear interrupt status */ | 753 | /* check for duplicate entry and find a free slot */ |
583 | l = dsi_read_reg(DSI_IRQSTATUS); | 754 | free_idx = -1; |
584 | dsi_write_reg(DSI_IRQSTATUS, l & ~DSI_IRQ_CHANNEL_MASK); | 755 | for (i = 0; i < isr_array_size; i++) { |
756 | isr_data = &isr_array[i]; | ||
585 | 757 | ||
586 | for (i = 0; i < 4; ++i) { | 758 | if (isr_data->isr == isr && isr_data->arg == arg && |
587 | l = dsi_read_reg(DSI_VC_IRQSTATUS(i)); | 759 | isr_data->mask == mask) { |
588 | dsi_write_reg(DSI_VC_IRQSTATUS(i), l); | 760 | return -EINVAL; |
761 | } | ||
762 | |||
763 | if (isr_data->isr == NULL && free_idx == -1) | ||
764 | free_idx = i; | ||
589 | } | 765 | } |
590 | 766 | ||
591 | l = dsi_read_reg(DSI_COMPLEXIO_IRQ_STATUS); | 767 | if (free_idx == -1) |
592 | dsi_write_reg(DSI_COMPLEXIO_IRQ_STATUS, l); | 768 | return -EBUSY; |
593 | 769 | ||
594 | /* enable error irqs */ | 770 | isr_data = &isr_array[free_idx]; |
595 | l = DSI_IRQ_ERROR_MASK; | 771 | isr_data->isr = isr; |
596 | #ifdef DSI_CATCH_MISSING_TE | 772 | isr_data->arg = arg; |
597 | l |= DSI_IRQ_TE_TRIGGER; | 773 | isr_data->mask = mask; |
598 | #endif | ||
599 | dsi_write_reg(DSI_IRQENABLE, l); | ||
600 | 774 | ||
601 | l = DSI_VC_IRQ_ERROR_MASK; | 775 | return 0; |
602 | for (i = 0; i < 4; ++i) | 776 | } |
603 | dsi_write_reg(DSI_VC_IRQENABLE(i), l); | 777 | |
778 | static int _dsi_unregister_isr(omap_dsi_isr_t isr, void *arg, u32 mask, | ||
779 | struct dsi_isr_data *isr_array, unsigned isr_array_size) | ||
780 | { | ||
781 | struct dsi_isr_data *isr_data; | ||
782 | int i; | ||
783 | |||
784 | for (i = 0; i < isr_array_size; i++) { | ||
785 | isr_data = &isr_array[i]; | ||
786 | if (isr_data->isr != isr || isr_data->arg != arg || | ||
787 | isr_data->mask != mask) | ||
788 | continue; | ||
789 | |||
790 | isr_data->isr = NULL; | ||
791 | isr_data->arg = NULL; | ||
792 | isr_data->mask = 0; | ||
793 | |||
794 | return 0; | ||
795 | } | ||
604 | 796 | ||
605 | l = DSI_CIO_IRQ_ERROR_MASK; | 797 | return -EINVAL; |
606 | dsi_write_reg(DSI_COMPLEXIO_IRQ_ENABLE, l); | ||
607 | } | 798 | } |
608 | 799 | ||
609 | static u32 dsi_get_errors(void) | 800 | static int dsi_register_isr(omap_dsi_isr_t isr, void *arg, u32 mask) |
610 | { | 801 | { |
611 | unsigned long flags; | 802 | unsigned long flags; |
612 | u32 e; | 803 | int r; |
613 | spin_lock_irqsave(&dsi.errors_lock, flags); | 804 | |
614 | e = dsi.errors; | 805 | spin_lock_irqsave(&dsi.irq_lock, flags); |
615 | dsi.errors = 0; | 806 | |
616 | spin_unlock_irqrestore(&dsi.errors_lock, flags); | 807 | r = _dsi_register_isr(isr, arg, mask, dsi.isr_tables.isr_table, |
617 | return e; | 808 | ARRAY_SIZE(dsi.isr_tables.isr_table)); |
809 | |||
810 | if (r == 0) | ||
811 | _omap_dsi_set_irqs(); | ||
812 | |||
813 | spin_unlock_irqrestore(&dsi.irq_lock, flags); | ||
814 | |||
815 | return r; | ||
618 | } | 816 | } |
619 | 817 | ||
620 | static void dsi_vc_enable_bta_irq(int channel) | 818 | static int dsi_unregister_isr(omap_dsi_isr_t isr, void *arg, u32 mask) |
621 | { | 819 | { |
622 | u32 l; | 820 | unsigned long flags; |
821 | int r; | ||
822 | |||
823 | spin_lock_irqsave(&dsi.irq_lock, flags); | ||
824 | |||
825 | r = _dsi_unregister_isr(isr, arg, mask, dsi.isr_tables.isr_table, | ||
826 | ARRAY_SIZE(dsi.isr_tables.isr_table)); | ||
827 | |||
828 | if (r == 0) | ||
829 | _omap_dsi_set_irqs(); | ||
623 | 830 | ||
624 | dsi_write_reg(DSI_VC_IRQSTATUS(channel), DSI_VC_IRQ_BTA); | 831 | spin_unlock_irqrestore(&dsi.irq_lock, flags); |
625 | 832 | ||
626 | l = dsi_read_reg(DSI_VC_IRQENABLE(channel)); | 833 | return r; |
627 | l |= DSI_VC_IRQ_BTA; | ||
628 | dsi_write_reg(DSI_VC_IRQENABLE(channel), l); | ||
629 | } | 834 | } |
630 | 835 | ||
631 | static void dsi_vc_disable_bta_irq(int channel) | 836 | static int dsi_register_isr_vc(int channel, omap_dsi_isr_t isr, void *arg, |
837 | u32 mask) | ||
632 | { | 838 | { |
633 | u32 l; | 839 | unsigned long flags; |
840 | int r; | ||
841 | |||
842 | spin_lock_irqsave(&dsi.irq_lock, flags); | ||
843 | |||
844 | r = _dsi_register_isr(isr, arg, mask, | ||
845 | dsi.isr_tables.isr_table_vc[channel], | ||
846 | ARRAY_SIZE(dsi.isr_tables.isr_table_vc[channel])); | ||
847 | |||
848 | if (r == 0) | ||
849 | _omap_dsi_set_irqs_vc(channel); | ||
850 | |||
851 | spin_unlock_irqrestore(&dsi.irq_lock, flags); | ||
852 | |||
853 | return r; | ||
854 | } | ||
855 | |||
856 | static int dsi_unregister_isr_vc(int channel, omap_dsi_isr_t isr, void *arg, | ||
857 | u32 mask) | ||
858 | { | ||
859 | unsigned long flags; | ||
860 | int r; | ||
861 | |||
862 | spin_lock_irqsave(&dsi.irq_lock, flags); | ||
863 | |||
864 | r = _dsi_unregister_isr(isr, arg, mask, | ||
865 | dsi.isr_tables.isr_table_vc[channel], | ||
866 | ARRAY_SIZE(dsi.isr_tables.isr_table_vc[channel])); | ||
867 | |||
868 | if (r == 0) | ||
869 | _omap_dsi_set_irqs_vc(channel); | ||
870 | |||
871 | spin_unlock_irqrestore(&dsi.irq_lock, flags); | ||
872 | |||
873 | return r; | ||
874 | } | ||
875 | |||
876 | static int dsi_register_isr_cio(omap_dsi_isr_t isr, void *arg, u32 mask) | ||
877 | { | ||
878 | unsigned long flags; | ||
879 | int r; | ||
880 | |||
881 | spin_lock_irqsave(&dsi.irq_lock, flags); | ||
882 | |||
883 | r = _dsi_register_isr(isr, arg, mask, dsi.isr_tables.isr_table_cio, | ||
884 | ARRAY_SIZE(dsi.isr_tables.isr_table_cio)); | ||
885 | |||
886 | if (r == 0) | ||
887 | _omap_dsi_set_irqs_cio(); | ||
888 | |||
889 | spin_unlock_irqrestore(&dsi.irq_lock, flags); | ||
890 | |||
891 | return r; | ||
892 | } | ||
893 | |||
894 | static int dsi_unregister_isr_cio(omap_dsi_isr_t isr, void *arg, u32 mask) | ||
895 | { | ||
896 | unsigned long flags; | ||
897 | int r; | ||
898 | |||
899 | spin_lock_irqsave(&dsi.irq_lock, flags); | ||
900 | |||
901 | r = _dsi_unregister_isr(isr, arg, mask, dsi.isr_tables.isr_table_cio, | ||
902 | ARRAY_SIZE(dsi.isr_tables.isr_table_cio)); | ||
903 | |||
904 | if (r == 0) | ||
905 | _omap_dsi_set_irqs_cio(); | ||
906 | |||
907 | spin_unlock_irqrestore(&dsi.irq_lock, flags); | ||
634 | 908 | ||
635 | l = dsi_read_reg(DSI_VC_IRQENABLE(channel)); | 909 | return r; |
636 | l &= ~DSI_VC_IRQ_BTA; | ||
637 | dsi_write_reg(DSI_VC_IRQENABLE(channel), l); | ||
638 | } | 910 | } |
639 | 911 | ||
640 | /* DSI func clock. this could also be DSI2_PLL_FCLK */ | 912 | static u32 dsi_get_errors(void) |
913 | { | ||
914 | unsigned long flags; | ||
915 | u32 e; | ||
916 | spin_lock_irqsave(&dsi.errors_lock, flags); | ||
917 | e = dsi.errors; | ||
918 | dsi.errors = 0; | ||
919 | spin_unlock_irqrestore(&dsi.errors_lock, flags); | ||
920 | return e; | ||
921 | } | ||
922 | |||
923 | /* DSI func clock. this could also be dsi_pll_hsdiv_dsi_clk */ | ||
641 | static inline void enable_clocks(bool enable) | 924 | static inline void enable_clocks(bool enable) |
642 | { | 925 | { |
643 | if (enable) | 926 | if (enable) |
644 | dss_clk_enable(DSS_CLK_ICK | DSS_CLK_FCK1); | 927 | dss_clk_enable(DSS_CLK_ICK | DSS_CLK_FCK); |
645 | else | 928 | else |
646 | dss_clk_disable(DSS_CLK_ICK | DSS_CLK_FCK1); | 929 | dss_clk_disable(DSS_CLK_ICK | DSS_CLK_FCK); |
647 | } | 930 | } |
648 | 931 | ||
649 | /* source clock for DSI PLL. this could also be PCLKFREE */ | 932 | /* source clock for DSI PLL. this could also be PCLKFREE */ |
650 | static inline void dsi_enable_pll_clock(bool enable) | 933 | static inline void dsi_enable_pll_clock(bool enable) |
651 | { | 934 | { |
652 | if (enable) | 935 | if (enable) |
653 | dss_clk_enable(DSS_CLK_FCK2); | 936 | dss_clk_enable(DSS_CLK_SYSCK); |
654 | else | 937 | else |
655 | dss_clk_disable(DSS_CLK_FCK2); | 938 | dss_clk_disable(DSS_CLK_SYSCK); |
656 | 939 | ||
657 | if (enable && dsi.pll_locked) { | 940 | if (enable && dsi.pll_locked) { |
658 | if (wait_for_bit_change(DSI_PLL_STATUS, 1, 1) != 1) | 941 | if (wait_for_bit_change(DSI_PLL_STATUS, 1, 1) != 1) |
@@ -707,14 +990,14 @@ static inline int dsi_if_enable(bool enable) | |||
707 | return 0; | 990 | return 0; |
708 | } | 991 | } |
709 | 992 | ||
710 | unsigned long dsi_get_dsi1_pll_rate(void) | 993 | unsigned long dsi_get_pll_hsdiv_dispc_rate(void) |
711 | { | 994 | { |
712 | return dsi.current_cinfo.dsi1_pll_fclk; | 995 | return dsi.current_cinfo.dsi_pll_hsdiv_dispc_clk; |
713 | } | 996 | } |
714 | 997 | ||
715 | static unsigned long dsi_get_dsi2_pll_rate(void) | 998 | static unsigned long dsi_get_pll_hsdiv_dsi_rate(void) |
716 | { | 999 | { |
717 | return dsi.current_cinfo.dsi2_pll_fclk; | 1000 | return dsi.current_cinfo.dsi_pll_hsdiv_dsi_clk; |
718 | } | 1001 | } |
719 | 1002 | ||
720 | static unsigned long dsi_get_txbyteclkhs(void) | 1003 | static unsigned long dsi_get_txbyteclkhs(void) |
@@ -726,12 +1009,12 @@ static unsigned long dsi_fclk_rate(void) | |||
726 | { | 1009 | { |
727 | unsigned long r; | 1010 | unsigned long r; |
728 | 1011 | ||
729 | if (dss_get_dsi_clk_source() == DSS_SRC_DSS1_ALWON_FCLK) { | 1012 | if (dss_get_dsi_clk_source() == DSS_CLK_SRC_FCK) { |
730 | /* DSI FCLK source is DSS1_ALWON_FCK, which is dss1_fck */ | 1013 | /* DSI FCLK source is DSS_CLK_FCK */ |
731 | r = dss_clk_get_rate(DSS_CLK_FCK1); | 1014 | r = dss_clk_get_rate(DSS_CLK_FCK); |
732 | } else { | 1015 | } else { |
733 | /* DSI FCLK source is DSI2_PLL_FCLK */ | 1016 | /* DSI FCLK source is dsi_pll_hsdiv_dsi_clk */ |
734 | r = dsi_get_dsi2_pll_rate(); | 1017 | r = dsi_get_pll_hsdiv_dsi_rate(); |
735 | } | 1018 | } |
736 | 1019 | ||
737 | return r; | 1020 | return r; |
@@ -745,7 +1028,7 @@ static int dsi_set_lp_clk_divisor(struct omap_dss_device *dssdev) | |||
745 | 1028 | ||
746 | lp_clk_div = dssdev->phy.dsi.div.lp_clk_div; | 1029 | lp_clk_div = dssdev->phy.dsi.div.lp_clk_div; |
747 | 1030 | ||
748 | if (lp_clk_div == 0 || lp_clk_div > LP_DIV_MAX) | 1031 | if (lp_clk_div == 0 || lp_clk_div > dsi.lpdiv_max) |
749 | return -EINVAL; | 1032 | return -EINVAL; |
750 | 1033 | ||
751 | dsi_fclk = dsi_fclk_rate(); | 1034 | dsi_fclk = dsi_fclk_rate(); |
@@ -795,22 +1078,22 @@ static int dsi_pll_power(enum dsi_pll_power_state state) | |||
795 | static int dsi_calc_clock_rates(struct omap_dss_device *dssdev, | 1078 | static int dsi_calc_clock_rates(struct omap_dss_device *dssdev, |
796 | struct dsi_clock_info *cinfo) | 1079 | struct dsi_clock_info *cinfo) |
797 | { | 1080 | { |
798 | if (cinfo->regn == 0 || cinfo->regn > REGN_MAX) | 1081 | if (cinfo->regn == 0 || cinfo->regn > dsi.regn_max) |
799 | return -EINVAL; | 1082 | return -EINVAL; |
800 | 1083 | ||
801 | if (cinfo->regm == 0 || cinfo->regm > REGM_MAX) | 1084 | if (cinfo->regm == 0 || cinfo->regm > dsi.regm_max) |
802 | return -EINVAL; | 1085 | return -EINVAL; |
803 | 1086 | ||
804 | if (cinfo->regm3 > REGM3_MAX) | 1087 | if (cinfo->regm_dispc > dsi.regm_dispc_max) |
805 | return -EINVAL; | 1088 | return -EINVAL; |
806 | 1089 | ||
807 | if (cinfo->regm4 > REGM4_MAX) | 1090 | if (cinfo->regm_dsi > dsi.regm_dsi_max) |
808 | return -EINVAL; | 1091 | return -EINVAL; |
809 | 1092 | ||
810 | if (cinfo->use_dss2_fck) { | 1093 | if (cinfo->use_sys_clk) { |
811 | cinfo->clkin = dss_clk_get_rate(DSS_CLK_FCK2); | 1094 | cinfo->clkin = dss_clk_get_rate(DSS_CLK_SYSCK); |
812 | /* XXX it is unclear if highfreq should be used | 1095 | /* XXX it is unclear if highfreq should be used |
813 | * with DSS2_FCK source also */ | 1096 | * with DSS_SYS_CLK source also */ |
814 | cinfo->highfreq = 0; | 1097 | cinfo->highfreq = 0; |
815 | } else { | 1098 | } else { |
816 | cinfo->clkin = dispc_pclk_rate(dssdev->manager->id); | 1099 | cinfo->clkin = dispc_pclk_rate(dssdev->manager->id); |
@@ -823,7 +1106,7 @@ static int dsi_calc_clock_rates(struct omap_dss_device *dssdev, | |||
823 | 1106 | ||
824 | cinfo->fint = cinfo->clkin / (cinfo->regn * (cinfo->highfreq ? 2 : 1)); | 1107 | cinfo->fint = cinfo->clkin / (cinfo->regn * (cinfo->highfreq ? 2 : 1)); |
825 | 1108 | ||
826 | if (cinfo->fint > FINT_MAX || cinfo->fint < FINT_MIN) | 1109 | if (cinfo->fint > dsi.fint_max || cinfo->fint < dsi.fint_min) |
827 | return -EINVAL; | 1110 | return -EINVAL; |
828 | 1111 | ||
829 | cinfo->clkin4ddr = 2 * cinfo->regm * cinfo->fint; | 1112 | cinfo->clkin4ddr = 2 * cinfo->regm * cinfo->fint; |
@@ -831,15 +1114,17 @@ static int dsi_calc_clock_rates(struct omap_dss_device *dssdev, | |||
831 | if (cinfo->clkin4ddr > 1800 * 1000 * 1000) | 1114 | if (cinfo->clkin4ddr > 1800 * 1000 * 1000) |
832 | return -EINVAL; | 1115 | return -EINVAL; |
833 | 1116 | ||
834 | if (cinfo->regm3 > 0) | 1117 | if (cinfo->regm_dispc > 0) |
835 | cinfo->dsi1_pll_fclk = cinfo->clkin4ddr / cinfo->regm3; | 1118 | cinfo->dsi_pll_hsdiv_dispc_clk = |
1119 | cinfo->clkin4ddr / cinfo->regm_dispc; | ||
836 | else | 1120 | else |
837 | cinfo->dsi1_pll_fclk = 0; | 1121 | cinfo->dsi_pll_hsdiv_dispc_clk = 0; |
838 | 1122 | ||
839 | if (cinfo->regm4 > 0) | 1123 | if (cinfo->regm_dsi > 0) |
840 | cinfo->dsi2_pll_fclk = cinfo->clkin4ddr / cinfo->regm4; | 1124 | cinfo->dsi_pll_hsdiv_dsi_clk = |
1125 | cinfo->clkin4ddr / cinfo->regm_dsi; | ||
841 | else | 1126 | else |
842 | cinfo->dsi2_pll_fclk = 0; | 1127 | cinfo->dsi_pll_hsdiv_dsi_clk = 0; |
843 | 1128 | ||
844 | return 0; | 1129 | return 0; |
845 | } | 1130 | } |
@@ -852,23 +1137,25 @@ int dsi_pll_calc_clock_div_pck(bool is_tft, unsigned long req_pck, | |||
852 | struct dispc_clock_info best_dispc; | 1137 | struct dispc_clock_info best_dispc; |
853 | int min_fck_per_pck; | 1138 | int min_fck_per_pck; |
854 | int match = 0; | 1139 | int match = 0; |
855 | unsigned long dss_clk_fck2; | 1140 | unsigned long dss_sys_clk, max_dss_fck; |
1141 | |||
1142 | dss_sys_clk = dss_clk_get_rate(DSS_CLK_SYSCK); | ||
856 | 1143 | ||
857 | dss_clk_fck2 = dss_clk_get_rate(DSS_CLK_FCK2); | 1144 | max_dss_fck = dss_feat_get_param_max(FEAT_PARAM_DSS_FCK); |
858 | 1145 | ||
859 | if (req_pck == dsi.cache_req_pck && | 1146 | if (req_pck == dsi.cache_req_pck && |
860 | dsi.cache_cinfo.clkin == dss_clk_fck2) { | 1147 | dsi.cache_cinfo.clkin == dss_sys_clk) { |
861 | DSSDBG("DSI clock info found from cache\n"); | 1148 | DSSDBG("DSI clock info found from cache\n"); |
862 | *dsi_cinfo = dsi.cache_cinfo; | 1149 | *dsi_cinfo = dsi.cache_cinfo; |
863 | dispc_find_clk_divs(is_tft, req_pck, dsi_cinfo->dsi1_pll_fclk, | 1150 | dispc_find_clk_divs(is_tft, req_pck, |
864 | dispc_cinfo); | 1151 | dsi_cinfo->dsi_pll_hsdiv_dispc_clk, dispc_cinfo); |
865 | return 0; | 1152 | return 0; |
866 | } | 1153 | } |
867 | 1154 | ||
868 | min_fck_per_pck = CONFIG_OMAP2_DSS_MIN_FCK_PER_PCK; | 1155 | min_fck_per_pck = CONFIG_OMAP2_DSS_MIN_FCK_PER_PCK; |
869 | 1156 | ||
870 | if (min_fck_per_pck && | 1157 | if (min_fck_per_pck && |
871 | req_pck * min_fck_per_pck > DISPC_MAX_FCK) { | 1158 | req_pck * min_fck_per_pck > max_dss_fck) { |
872 | DSSERR("Requested pixel clock not possible with the current " | 1159 | DSSERR("Requested pixel clock not possible with the current " |
873 | "OMAP2_DSS_MIN_FCK_PER_PCK setting. Turning " | 1160 | "OMAP2_DSS_MIN_FCK_PER_PCK setting. Turning " |
874 | "the constraint off.\n"); | 1161 | "the constraint off.\n"); |
@@ -882,24 +1169,24 @@ retry: | |||
882 | memset(&best_dispc, 0, sizeof(best_dispc)); | 1169 | memset(&best_dispc, 0, sizeof(best_dispc)); |
883 | 1170 | ||
884 | memset(&cur, 0, sizeof(cur)); | 1171 | memset(&cur, 0, sizeof(cur)); |
885 | cur.clkin = dss_clk_fck2; | 1172 | cur.clkin = dss_sys_clk; |
886 | cur.use_dss2_fck = 1; | 1173 | cur.use_sys_clk = 1; |
887 | cur.highfreq = 0; | 1174 | cur.highfreq = 0; |
888 | 1175 | ||
889 | /* no highfreq: 0.75MHz < Fint = clkin / regn < 2.1MHz */ | 1176 | /* no highfreq: 0.75MHz < Fint = clkin / regn < 2.1MHz */ |
890 | /* highfreq: 0.75MHz < Fint = clkin / (2*regn) < 2.1MHz */ | 1177 | /* highfreq: 0.75MHz < Fint = clkin / (2*regn) < 2.1MHz */ |
891 | /* To reduce PLL lock time, keep Fint high (around 2 MHz) */ | 1178 | /* To reduce PLL lock time, keep Fint high (around 2 MHz) */ |
892 | for (cur.regn = 1; cur.regn < REGN_MAX; ++cur.regn) { | 1179 | for (cur.regn = 1; cur.regn < dsi.regn_max; ++cur.regn) { |
893 | if (cur.highfreq == 0) | 1180 | if (cur.highfreq == 0) |
894 | cur.fint = cur.clkin / cur.regn; | 1181 | cur.fint = cur.clkin / cur.regn; |
895 | else | 1182 | else |
896 | cur.fint = cur.clkin / (2 * cur.regn); | 1183 | cur.fint = cur.clkin / (2 * cur.regn); |
897 | 1184 | ||
898 | if (cur.fint > FINT_MAX || cur.fint < FINT_MIN) | 1185 | if (cur.fint > dsi.fint_max || cur.fint < dsi.fint_min) |
899 | continue; | 1186 | continue; |
900 | 1187 | ||
901 | /* DSIPHY(MHz) = (2 * regm / regn) * (clkin / (highfreq + 1)) */ | 1188 | /* DSIPHY(MHz) = (2 * regm / regn) * (clkin / (highfreq + 1)) */ |
902 | for (cur.regm = 1; cur.regm < REGM_MAX; ++cur.regm) { | 1189 | for (cur.regm = 1; cur.regm < dsi.regm_max; ++cur.regm) { |
903 | unsigned long a, b; | 1190 | unsigned long a, b; |
904 | 1191 | ||
905 | a = 2 * cur.regm * (cur.clkin/1000); | 1192 | a = 2 * cur.regm * (cur.clkin/1000); |
@@ -909,30 +1196,32 @@ retry: | |||
909 | if (cur.clkin4ddr > 1800 * 1000 * 1000) | 1196 | if (cur.clkin4ddr > 1800 * 1000 * 1000) |
910 | break; | 1197 | break; |
911 | 1198 | ||
912 | /* DSI1_PLL_FCLK(MHz) = DSIPHY(MHz) / regm3 < 173MHz */ | 1199 | /* dsi_pll_hsdiv_dispc_clk(MHz) = |
913 | for (cur.regm3 = 1; cur.regm3 < REGM3_MAX; | 1200 | * DSIPHY(MHz) / regm_dispc < 173MHz/186Mhz */ |
914 | ++cur.regm3) { | 1201 | for (cur.regm_dispc = 1; cur.regm_dispc < dsi.regm_dispc_max; |
1202 | ++cur.regm_dispc) { | ||
915 | struct dispc_clock_info cur_dispc; | 1203 | struct dispc_clock_info cur_dispc; |
916 | cur.dsi1_pll_fclk = cur.clkin4ddr / cur.regm3; | 1204 | cur.dsi_pll_hsdiv_dispc_clk = |
1205 | cur.clkin4ddr / cur.regm_dispc; | ||
917 | 1206 | ||
918 | /* this will narrow down the search a bit, | 1207 | /* this will narrow down the search a bit, |
919 | * but still give pixclocks below what was | 1208 | * but still give pixclocks below what was |
920 | * requested */ | 1209 | * requested */ |
921 | if (cur.dsi1_pll_fclk < req_pck) | 1210 | if (cur.dsi_pll_hsdiv_dispc_clk < req_pck) |
922 | break; | 1211 | break; |
923 | 1212 | ||
924 | if (cur.dsi1_pll_fclk > DISPC_MAX_FCK) | 1213 | if (cur.dsi_pll_hsdiv_dispc_clk > max_dss_fck) |
925 | continue; | 1214 | continue; |
926 | 1215 | ||
927 | if (min_fck_per_pck && | 1216 | if (min_fck_per_pck && |
928 | cur.dsi1_pll_fclk < | 1217 | cur.dsi_pll_hsdiv_dispc_clk < |
929 | req_pck * min_fck_per_pck) | 1218 | req_pck * min_fck_per_pck) |
930 | continue; | 1219 | continue; |
931 | 1220 | ||
932 | match = 1; | 1221 | match = 1; |
933 | 1222 | ||
934 | dispc_find_clk_divs(is_tft, req_pck, | 1223 | dispc_find_clk_divs(is_tft, req_pck, |
935 | cur.dsi1_pll_fclk, | 1224 | cur.dsi_pll_hsdiv_dispc_clk, |
936 | &cur_dispc); | 1225 | &cur_dispc); |
937 | 1226 | ||
938 | if (abs(cur_dispc.pck - req_pck) < | 1227 | if (abs(cur_dispc.pck - req_pck) < |
@@ -961,9 +1250,9 @@ found: | |||
961 | return -EINVAL; | 1250 | return -EINVAL; |
962 | } | 1251 | } |
963 | 1252 | ||
964 | /* DSI2_PLL_FCLK (regm4) is not used */ | 1253 | /* dsi_pll_hsdiv_dsi_clk (regm_dsi) is not used */ |
965 | best.regm4 = 0; | 1254 | best.regm_dsi = 0; |
966 | best.dsi2_pll_fclk = 0; | 1255 | best.dsi_pll_hsdiv_dsi_clk = 0; |
967 | 1256 | ||
968 | if (dsi_cinfo) | 1257 | if (dsi_cinfo) |
969 | *dsi_cinfo = best; | 1258 | *dsi_cinfo = best; |
@@ -982,23 +1271,27 @@ int dsi_pll_set_clock_div(struct dsi_clock_info *cinfo) | |||
982 | int r = 0; | 1271 | int r = 0; |
983 | u32 l; | 1272 | u32 l; |
984 | int f; | 1273 | int f; |
1274 | u8 regn_start, regn_end, regm_start, regm_end; | ||
1275 | u8 regm_dispc_start, regm_dispc_end, regm_dsi_start, regm_dsi_end; | ||
985 | 1276 | ||
986 | DSSDBGF(); | 1277 | DSSDBGF(); |
987 | 1278 | ||
988 | dsi.current_cinfo.fint = cinfo->fint; | 1279 | dsi.current_cinfo.fint = cinfo->fint; |
989 | dsi.current_cinfo.clkin4ddr = cinfo->clkin4ddr; | 1280 | dsi.current_cinfo.clkin4ddr = cinfo->clkin4ddr; |
990 | dsi.current_cinfo.dsi1_pll_fclk = cinfo->dsi1_pll_fclk; | 1281 | dsi.current_cinfo.dsi_pll_hsdiv_dispc_clk = |
991 | dsi.current_cinfo.dsi2_pll_fclk = cinfo->dsi2_pll_fclk; | 1282 | cinfo->dsi_pll_hsdiv_dispc_clk; |
1283 | dsi.current_cinfo.dsi_pll_hsdiv_dsi_clk = | ||
1284 | cinfo->dsi_pll_hsdiv_dsi_clk; | ||
992 | 1285 | ||
993 | dsi.current_cinfo.regn = cinfo->regn; | 1286 | dsi.current_cinfo.regn = cinfo->regn; |
994 | dsi.current_cinfo.regm = cinfo->regm; | 1287 | dsi.current_cinfo.regm = cinfo->regm; |
995 | dsi.current_cinfo.regm3 = cinfo->regm3; | 1288 | dsi.current_cinfo.regm_dispc = cinfo->regm_dispc; |
996 | dsi.current_cinfo.regm4 = cinfo->regm4; | 1289 | dsi.current_cinfo.regm_dsi = cinfo->regm_dsi; |
997 | 1290 | ||
998 | DSSDBG("DSI Fint %ld\n", cinfo->fint); | 1291 | DSSDBG("DSI Fint %ld\n", cinfo->fint); |
999 | 1292 | ||
1000 | DSSDBG("clkin (%s) rate %ld, highfreq %d\n", | 1293 | DSSDBG("clkin (%s) rate %ld, highfreq %d\n", |
1001 | cinfo->use_dss2_fck ? "dss2_fck" : "pclkfree", | 1294 | cinfo->use_sys_clk ? "dss_sys_clk" : "pclkfree", |
1002 | cinfo->clkin, | 1295 | cinfo->clkin, |
1003 | cinfo->highfreq); | 1296 | cinfo->highfreq); |
1004 | 1297 | ||
@@ -1015,24 +1308,39 @@ int dsi_pll_set_clock_div(struct dsi_clock_info *cinfo) | |||
1015 | 1308 | ||
1016 | DSSDBG("Clock lane freq %ld Hz\n", cinfo->clkin4ddr / 4); | 1309 | DSSDBG("Clock lane freq %ld Hz\n", cinfo->clkin4ddr / 4); |
1017 | 1310 | ||
1018 | DSSDBG("regm3 = %d, dsi1_pll_fclk = %lu\n", | 1311 | DSSDBG("regm_dispc = %d, %s (%s) = %lu\n", cinfo->regm_dispc, |
1019 | cinfo->regm3, cinfo->dsi1_pll_fclk); | 1312 | dss_get_generic_clk_source_name(DSS_CLK_SRC_DSI_PLL_HSDIV_DISPC), |
1020 | DSSDBG("regm4 = %d, dsi2_pll_fclk = %lu\n", | 1313 | dss_feat_get_clk_source_name(DSS_CLK_SRC_DSI_PLL_HSDIV_DISPC), |
1021 | cinfo->regm4, cinfo->dsi2_pll_fclk); | 1314 | cinfo->dsi_pll_hsdiv_dispc_clk); |
1315 | DSSDBG("regm_dsi = %d, %s (%s) = %lu\n", cinfo->regm_dsi, | ||
1316 | dss_get_generic_clk_source_name(DSS_CLK_SRC_DSI_PLL_HSDIV_DSI), | ||
1317 | dss_feat_get_clk_source_name(DSS_CLK_SRC_DSI_PLL_HSDIV_DSI), | ||
1318 | cinfo->dsi_pll_hsdiv_dsi_clk); | ||
1319 | |||
1320 | dss_feat_get_reg_field(FEAT_REG_DSIPLL_REGN, ®n_start, ®n_end); | ||
1321 | dss_feat_get_reg_field(FEAT_REG_DSIPLL_REGM, ®m_start, ®m_end); | ||
1322 | dss_feat_get_reg_field(FEAT_REG_DSIPLL_REGM_DISPC, ®m_dispc_start, | ||
1323 | ®m_dispc_end); | ||
1324 | dss_feat_get_reg_field(FEAT_REG_DSIPLL_REGM_DSI, ®m_dsi_start, | ||
1325 | ®m_dsi_end); | ||
1022 | 1326 | ||
1023 | REG_FLD_MOD(DSI_PLL_CONTROL, 0, 0, 0); /* DSI_PLL_AUTOMODE = manual */ | 1327 | REG_FLD_MOD(DSI_PLL_CONTROL, 0, 0, 0); /* DSI_PLL_AUTOMODE = manual */ |
1024 | 1328 | ||
1025 | l = dsi_read_reg(DSI_PLL_CONFIGURATION1); | 1329 | l = dsi_read_reg(DSI_PLL_CONFIGURATION1); |
1026 | l = FLD_MOD(l, 1, 0, 0); /* DSI_PLL_STOPMODE */ | 1330 | l = FLD_MOD(l, 1, 0, 0); /* DSI_PLL_STOPMODE */ |
1027 | l = FLD_MOD(l, cinfo->regn - 1, 7, 1); /* DSI_PLL_REGN */ | 1331 | /* DSI_PLL_REGN */ |
1028 | l = FLD_MOD(l, cinfo->regm, 18, 8); /* DSI_PLL_REGM */ | 1332 | l = FLD_MOD(l, cinfo->regn - 1, regn_start, regn_end); |
1029 | l = FLD_MOD(l, cinfo->regm3 > 0 ? cinfo->regm3 - 1 : 0, | 1333 | /* DSI_PLL_REGM */ |
1030 | 22, 19); /* DSI_CLOCK_DIV */ | 1334 | l = FLD_MOD(l, cinfo->regm, regm_start, regm_end); |
1031 | l = FLD_MOD(l, cinfo->regm4 > 0 ? cinfo->regm4 - 1 : 0, | 1335 | /* DSI_CLOCK_DIV */ |
1032 | 26, 23); /* DSIPROTO_CLOCK_DIV */ | 1336 | l = FLD_MOD(l, cinfo->regm_dispc > 0 ? cinfo->regm_dispc - 1 : 0, |
1337 | regm_dispc_start, regm_dispc_end); | ||
1338 | /* DSIPROTO_CLOCK_DIV */ | ||
1339 | l = FLD_MOD(l, cinfo->regm_dsi > 0 ? cinfo->regm_dsi - 1 : 0, | ||
1340 | regm_dsi_start, regm_dsi_end); | ||
1033 | dsi_write_reg(DSI_PLL_CONFIGURATION1, l); | 1341 | dsi_write_reg(DSI_PLL_CONFIGURATION1, l); |
1034 | 1342 | ||
1035 | BUG_ON(cinfo->fint < 750000 || cinfo->fint > 2100000); | 1343 | BUG_ON(cinfo->fint < dsi.fint_min || cinfo->fint > dsi.fint_max); |
1036 | if (cinfo->fint < 1000000) | 1344 | if (cinfo->fint < 1000000) |
1037 | f = 0x3; | 1345 | f = 0x3; |
1038 | else if (cinfo->fint < 1250000) | 1346 | else if (cinfo->fint < 1250000) |
@@ -1046,7 +1354,7 @@ int dsi_pll_set_clock_div(struct dsi_clock_info *cinfo) | |||
1046 | 1354 | ||
1047 | l = dsi_read_reg(DSI_PLL_CONFIGURATION2); | 1355 | l = dsi_read_reg(DSI_PLL_CONFIGURATION2); |
1048 | l = FLD_MOD(l, f, 4, 1); /* DSI_PLL_FREQSEL */ | 1356 | l = FLD_MOD(l, f, 4, 1); /* DSI_PLL_FREQSEL */ |
1049 | l = FLD_MOD(l, cinfo->use_dss2_fck ? 0 : 1, | 1357 | l = FLD_MOD(l, cinfo->use_sys_clk ? 0 : 1, |
1050 | 11, 11); /* DSI_PLL_CLKSEL */ | 1358 | 11, 11); /* DSI_PLL_CLKSEL */ |
1051 | l = FLD_MOD(l, cinfo->highfreq, | 1359 | l = FLD_MOD(l, cinfo->highfreq, |
1052 | 12, 12); /* DSI_PLL_HIGHFREQ */ | 1360 | 12, 12); /* DSI_PLL_HIGHFREQ */ |
@@ -1101,6 +1409,26 @@ int dsi_pll_init(struct omap_dss_device *dssdev, bool enable_hsclk, | |||
1101 | 1409 | ||
1102 | DSSDBG("PLL init\n"); | 1410 | DSSDBG("PLL init\n"); |
1103 | 1411 | ||
1412 | #ifdef CONFIG_OMAP2_DSS_USE_DSI_PLL | ||
1413 | /* | ||
1414 | * HACK: this is just a quick hack to get the USE_DSI_PLL | ||
1415 | * option working. USE_DSI_PLL is itself a big hack, and | ||
1416 | * should be removed. | ||
1417 | */ | ||
1418 | if (dsi.vdds_dsi_reg == NULL) { | ||
1419 | struct regulator *vdds_dsi; | ||
1420 | |||
1421 | vdds_dsi = regulator_get(&dsi.pdev->dev, "vdds_dsi"); | ||
1422 | |||
1423 | if (IS_ERR(vdds_dsi)) { | ||
1424 | DSSERR("can't get VDDS_DSI regulator\n"); | ||
1425 | return PTR_ERR(vdds_dsi); | ||
1426 | } | ||
1427 | |||
1428 | dsi.vdds_dsi_reg = vdds_dsi; | ||
1429 | } | ||
1430 | #endif | ||
1431 | |||
1104 | enable_clocks(1); | 1432 | enable_clocks(1); |
1105 | dsi_enable_pll_clock(1); | 1433 | dsi_enable_pll_clock(1); |
1106 | 1434 | ||
@@ -1162,6 +1490,10 @@ void dsi_dump_clocks(struct seq_file *s) | |||
1162 | { | 1490 | { |
1163 | int clksel; | 1491 | int clksel; |
1164 | struct dsi_clock_info *cinfo = &dsi.current_cinfo; | 1492 | struct dsi_clock_info *cinfo = &dsi.current_cinfo; |
1493 | enum dss_clk_source dispc_clk_src, dsi_clk_src; | ||
1494 | |||
1495 | dispc_clk_src = dss_get_dispc_clk_source(); | ||
1496 | dsi_clk_src = dss_get_dsi_clk_source(); | ||
1165 | 1497 | ||
1166 | enable_clocks(1); | 1498 | enable_clocks(1); |
1167 | 1499 | ||
@@ -1171,30 +1503,34 @@ void dsi_dump_clocks(struct seq_file *s) | |||
1171 | 1503 | ||
1172 | seq_printf(s, "dsi pll source = %s\n", | 1504 | seq_printf(s, "dsi pll source = %s\n", |
1173 | clksel == 0 ? | 1505 | clksel == 0 ? |
1174 | "dss2_alwon_fclk" : "pclkfree"); | 1506 | "dss_sys_clk" : "pclkfree"); |
1175 | 1507 | ||
1176 | seq_printf(s, "Fint\t\t%-16luregn %u\n", cinfo->fint, cinfo->regn); | 1508 | seq_printf(s, "Fint\t\t%-16luregn %u\n", cinfo->fint, cinfo->regn); |
1177 | 1509 | ||
1178 | seq_printf(s, "CLKIN4DDR\t%-16luregm %u\n", | 1510 | seq_printf(s, "CLKIN4DDR\t%-16luregm %u\n", |
1179 | cinfo->clkin4ddr, cinfo->regm); | 1511 | cinfo->clkin4ddr, cinfo->regm); |
1180 | 1512 | ||
1181 | seq_printf(s, "dsi1_pll_fck\t%-16luregm3 %u\t(%s)\n", | 1513 | seq_printf(s, "%s (%s)\t%-16luregm_dispc %u\t(%s)\n", |
1182 | cinfo->dsi1_pll_fclk, | 1514 | dss_get_generic_clk_source_name(dispc_clk_src), |
1183 | cinfo->regm3, | 1515 | dss_feat_get_clk_source_name(dispc_clk_src), |
1184 | dss_get_dispc_clk_source() == DSS_SRC_DSS1_ALWON_FCLK ? | 1516 | cinfo->dsi_pll_hsdiv_dispc_clk, |
1517 | cinfo->regm_dispc, | ||
1518 | dispc_clk_src == DSS_CLK_SRC_FCK ? | ||
1185 | "off" : "on"); | 1519 | "off" : "on"); |
1186 | 1520 | ||
1187 | seq_printf(s, "dsi2_pll_fck\t%-16luregm4 %u\t(%s)\n", | 1521 | seq_printf(s, "%s (%s)\t%-16luregm_dsi %u\t(%s)\n", |
1188 | cinfo->dsi2_pll_fclk, | 1522 | dss_get_generic_clk_source_name(dsi_clk_src), |
1189 | cinfo->regm4, | 1523 | dss_feat_get_clk_source_name(dsi_clk_src), |
1190 | dss_get_dsi_clk_source() == DSS_SRC_DSS1_ALWON_FCLK ? | 1524 | cinfo->dsi_pll_hsdiv_dsi_clk, |
1525 | cinfo->regm_dsi, | ||
1526 | dsi_clk_src == DSS_CLK_SRC_FCK ? | ||
1191 | "off" : "on"); | 1527 | "off" : "on"); |
1192 | 1528 | ||
1193 | seq_printf(s, "- DSI -\n"); | 1529 | seq_printf(s, "- DSI -\n"); |
1194 | 1530 | ||
1195 | seq_printf(s, "dsi fclk source = %s\n", | 1531 | seq_printf(s, "dsi fclk source = %s (%s)\n", |
1196 | dss_get_dsi_clk_source() == DSS_SRC_DSS1_ALWON_FCLK ? | 1532 | dss_get_generic_clk_source_name(dsi_clk_src), |
1197 | "dss1_alwon_fclk" : "dsi2_pll_fclk"); | 1533 | dss_feat_get_clk_source_name(dsi_clk_src)); |
1198 | 1534 | ||
1199 | seq_printf(s, "DSI_FCLK\t%lu\n", dsi_fclk_rate()); | 1535 | seq_printf(s, "DSI_FCLK\t%lu\n", dsi_fclk_rate()); |
1200 | 1536 | ||
@@ -1306,7 +1642,7 @@ void dsi_dump_regs(struct seq_file *s) | |||
1306 | { | 1642 | { |
1307 | #define DUMPREG(r) seq_printf(s, "%-35s %08x\n", #r, dsi_read_reg(r)) | 1643 | #define DUMPREG(r) seq_printf(s, "%-35s %08x\n", #r, dsi_read_reg(r)) |
1308 | 1644 | ||
1309 | dss_clk_enable(DSS_CLK_ICK | DSS_CLK_FCK1); | 1645 | dss_clk_enable(DSS_CLK_ICK | DSS_CLK_FCK); |
1310 | 1646 | ||
1311 | DUMPREG(DSI_REVISION); | 1647 | DUMPREG(DSI_REVISION); |
1312 | DUMPREG(DSI_SYSCONFIG); | 1648 | DUMPREG(DSI_SYSCONFIG); |
@@ -1378,7 +1714,7 @@ void dsi_dump_regs(struct seq_file *s) | |||
1378 | DUMPREG(DSI_PLL_CONFIGURATION1); | 1714 | DUMPREG(DSI_PLL_CONFIGURATION1); |
1379 | DUMPREG(DSI_PLL_CONFIGURATION2); | 1715 | DUMPREG(DSI_PLL_CONFIGURATION2); |
1380 | 1716 | ||
1381 | dss_clk_disable(DSS_CLK_ICK | DSS_CLK_FCK1); | 1717 | dss_clk_disable(DSS_CLK_ICK | DSS_CLK_FCK); |
1382 | #undef DUMPREG | 1718 | #undef DUMPREG |
1383 | } | 1719 | } |
1384 | 1720 | ||
@@ -1622,20 +1958,6 @@ static int _dsi_reset(void) | |||
1622 | return _dsi_wait_reset(); | 1958 | return _dsi_wait_reset(); |
1623 | } | 1959 | } |
1624 | 1960 | ||
1625 | static void dsi_reset_tx_fifo(int channel) | ||
1626 | { | ||
1627 | u32 mask; | ||
1628 | u32 l; | ||
1629 | |||
1630 | /* set fifosize of the channel to 0, then return the old size */ | ||
1631 | l = dsi_read_reg(DSI_TX_FIFO_VC_SIZE); | ||
1632 | |||
1633 | mask = FLD_MASK((8 * channel) + 7, (8 * channel) + 4); | ||
1634 | dsi_write_reg(DSI_TX_FIFO_VC_SIZE, l & ~mask); | ||
1635 | |||
1636 | dsi_write_reg(DSI_TX_FIFO_VC_SIZE, l); | ||
1637 | } | ||
1638 | |||
1639 | static void dsi_config_tx_fifo(enum fifo_size size1, enum fifo_size size2, | 1961 | static void dsi_config_tx_fifo(enum fifo_size size1, enum fifo_size size2, |
1640 | enum fifo_size size3, enum fifo_size size4) | 1962 | enum fifo_size size3, enum fifo_size size4) |
1641 | { | 1963 | { |
@@ -1753,8 +2075,6 @@ static void dsi_vc_initial_config(int channel) | |||
1753 | r = FLD_MOD(r, 4, 23, 21); /* DMA_TX_REQ_NB = no dma */ | 2075 | r = FLD_MOD(r, 4, 23, 21); /* DMA_TX_REQ_NB = no dma */ |
1754 | 2076 | ||
1755 | dsi_write_reg(DSI_VC_CTRL(channel), r); | 2077 | dsi_write_reg(DSI_VC_CTRL(channel), r); |
1756 | |||
1757 | dsi.vc[channel].mode = DSI_VC_MODE_L4; | ||
1758 | } | 2078 | } |
1759 | 2079 | ||
1760 | static int dsi_vc_config_l4(int channel) | 2080 | static int dsi_vc_config_l4(int channel) |
@@ -1922,33 +2242,44 @@ static int dsi_vc_send_bta(int channel) | |||
1922 | 2242 | ||
1923 | int dsi_vc_send_bta_sync(int channel) | 2243 | int dsi_vc_send_bta_sync(int channel) |
1924 | { | 2244 | { |
2245 | DECLARE_COMPLETION_ONSTACK(completion); | ||
1925 | int r = 0; | 2246 | int r = 0; |
1926 | u32 err; | 2247 | u32 err; |
1927 | 2248 | ||
1928 | INIT_COMPLETION(dsi.bta_completion); | 2249 | r = dsi_register_isr_vc(channel, dsi_completion_handler, |
2250 | &completion, DSI_VC_IRQ_BTA); | ||
2251 | if (r) | ||
2252 | goto err0; | ||
1929 | 2253 | ||
1930 | dsi_vc_enable_bta_irq(channel); | 2254 | r = dsi_register_isr(dsi_completion_handler, &completion, |
2255 | DSI_IRQ_ERROR_MASK); | ||
2256 | if (r) | ||
2257 | goto err1; | ||
1931 | 2258 | ||
1932 | r = dsi_vc_send_bta(channel); | 2259 | r = dsi_vc_send_bta(channel); |
1933 | if (r) | 2260 | if (r) |
1934 | goto err; | 2261 | goto err2; |
1935 | 2262 | ||
1936 | if (wait_for_completion_timeout(&dsi.bta_completion, | 2263 | if (wait_for_completion_timeout(&completion, |
1937 | msecs_to_jiffies(500)) == 0) { | 2264 | msecs_to_jiffies(500)) == 0) { |
1938 | DSSERR("Failed to receive BTA\n"); | 2265 | DSSERR("Failed to receive BTA\n"); |
1939 | r = -EIO; | 2266 | r = -EIO; |
1940 | goto err; | 2267 | goto err2; |
1941 | } | 2268 | } |
1942 | 2269 | ||
1943 | err = dsi_get_errors(); | 2270 | err = dsi_get_errors(); |
1944 | if (err) { | 2271 | if (err) { |
1945 | DSSERR("Error while sending BTA: %x\n", err); | 2272 | DSSERR("Error while sending BTA: %x\n", err); |
1946 | r = -EIO; | 2273 | r = -EIO; |
1947 | goto err; | 2274 | goto err2; |
1948 | } | 2275 | } |
1949 | err: | 2276 | err2: |
1950 | dsi_vc_disable_bta_irq(channel); | 2277 | dsi_unregister_isr(dsi_completion_handler, &completion, |
1951 | 2278 | DSI_IRQ_ERROR_MASK); | |
2279 | err1: | ||
2280 | dsi_unregister_isr_vc(channel, dsi_completion_handler, | ||
2281 | &completion, DSI_VC_IRQ_BTA); | ||
2282 | err0: | ||
1952 | return r; | 2283 | return r; |
1953 | } | 2284 | } |
1954 | EXPORT_SYMBOL(dsi_vc_send_bta_sync); | 2285 | EXPORT_SYMBOL(dsi_vc_send_bta_sync); |
@@ -1961,7 +2292,7 @@ static inline void dsi_vc_write_long_header(int channel, u8 data_type, | |||
1961 | 2292 | ||
1962 | WARN_ON(!dsi_bus_is_locked()); | 2293 | WARN_ON(!dsi_bus_is_locked()); |
1963 | 2294 | ||
1964 | data_id = data_type | channel << 6; | 2295 | data_id = data_type | dsi.vc[channel].vc_id << 6; |
1965 | 2296 | ||
1966 | val = FLD_VAL(data_id, 7, 0) | FLD_VAL(len, 23, 8) | | 2297 | val = FLD_VAL(data_id, 7, 0) | FLD_VAL(len, 23, 8) | |
1967 | FLD_VAL(ecc, 31, 24); | 2298 | FLD_VAL(ecc, 31, 24); |
@@ -2064,7 +2395,7 @@ static int dsi_vc_send_short(int channel, u8 data_type, u16 data, u8 ecc) | |||
2064 | return -EINVAL; | 2395 | return -EINVAL; |
2065 | } | 2396 | } |
2066 | 2397 | ||
2067 | data_id = data_type | channel << 6; | 2398 | data_id = data_type | dsi.vc[channel].vc_id << 6; |
2068 | 2399 | ||
2069 | r = (data_id << 0) | (data << 8) | (ecc << 24); | 2400 | r = (data_id << 0) | (data << 8) | (ecc << 24); |
2070 | 2401 | ||
@@ -2762,19 +3093,20 @@ static void dsi_te_timeout(unsigned long arg) | |||
2762 | } | 3093 | } |
2763 | #endif | 3094 | #endif |
2764 | 3095 | ||
3096 | static void dsi_framedone_bta_callback(void *data, u32 mask); | ||
3097 | |||
2765 | static void dsi_handle_framedone(int error) | 3098 | static void dsi_handle_framedone(int error) |
2766 | { | 3099 | { |
2767 | const int channel = dsi.update_channel; | 3100 | const int channel = dsi.update_channel; |
2768 | 3101 | ||
2769 | cancel_delayed_work(&dsi.framedone_timeout_work); | 3102 | dsi_unregister_isr_vc(channel, dsi_framedone_bta_callback, |
3103 | NULL, DSI_VC_IRQ_BTA); | ||
2770 | 3104 | ||
2771 | dsi_vc_disable_bta_irq(channel); | 3105 | cancel_delayed_work(&dsi.framedone_timeout_work); |
2772 | 3106 | ||
2773 | /* SIDLEMODE back to smart-idle */ | 3107 | /* SIDLEMODE back to smart-idle */ |
2774 | dispc_enable_sidle(); | 3108 | dispc_enable_sidle(); |
2775 | 3109 | ||
2776 | dsi.bta_callback = NULL; | ||
2777 | |||
2778 | if (dsi.te_enabled) { | 3110 | if (dsi.te_enabled) { |
2779 | /* enable LP_RX_TO again after the TE */ | 3111 | /* enable LP_RX_TO again after the TE */ |
2780 | REG_FLD_MOD(DSI_TIMING2, 1, 15, 15); /* LP_RX_TO */ | 3112 | REG_FLD_MOD(DSI_TIMING2, 1, 15, 15); /* LP_RX_TO */ |
@@ -2808,7 +3140,7 @@ static void dsi_framedone_timeout_work_callback(struct work_struct *work) | |||
2808 | dsi_handle_framedone(-ETIMEDOUT); | 3140 | dsi_handle_framedone(-ETIMEDOUT); |
2809 | } | 3141 | } |
2810 | 3142 | ||
2811 | static void dsi_framedone_bta_callback(void) | 3143 | static void dsi_framedone_bta_callback(void *data, u32 mask) |
2812 | { | 3144 | { |
2813 | dsi_handle_framedone(0); | 3145 | dsi_handle_framedone(0); |
2814 | 3146 | ||
@@ -2848,15 +3180,19 @@ static void dsi_framedone_irq_callback(void *data, u32 mask) | |||
2848 | * asynchronously. | 3180 | * asynchronously. |
2849 | * */ | 3181 | * */ |
2850 | 3182 | ||
2851 | dsi.bta_callback = dsi_framedone_bta_callback; | 3183 | r = dsi_register_isr_vc(channel, dsi_framedone_bta_callback, |
2852 | 3184 | NULL, DSI_VC_IRQ_BTA); | |
2853 | barrier(); | 3185 | if (r) { |
2854 | 3186 | DSSERR("Failed to register BTA ISR\n"); | |
2855 | dsi_vc_enable_bta_irq(channel); | 3187 | dsi_handle_framedone(-EIO); |
3188 | return; | ||
3189 | } | ||
2856 | 3190 | ||
2857 | r = dsi_vc_send_bta(channel); | 3191 | r = dsi_vc_send_bta(channel); |
2858 | if (r) { | 3192 | if (r) { |
2859 | DSSERR("BTA after framedone failed\n"); | 3193 | DSSERR("BTA after framedone failed\n"); |
3194 | dsi_unregister_isr_vc(channel, dsi_framedone_bta_callback, | ||
3195 | NULL, DSI_VC_IRQ_BTA); | ||
2860 | dsi_handle_framedone(-EIO); | 3196 | dsi_handle_framedone(-EIO); |
2861 | } | 3197 | } |
2862 | } | 3198 | } |
@@ -2984,12 +3320,12 @@ static int dsi_configure_dsi_clocks(struct omap_dss_device *dssdev) | |||
2984 | struct dsi_clock_info cinfo; | 3320 | struct dsi_clock_info cinfo; |
2985 | int r; | 3321 | int r; |
2986 | 3322 | ||
2987 | /* we always use DSS2_FCK as input clock */ | 3323 | /* we always use DSS_CLK_SYSCK as input clock */ |
2988 | cinfo.use_dss2_fck = true; | 3324 | cinfo.use_sys_clk = true; |
2989 | cinfo.regn = dssdev->phy.dsi.div.regn; | 3325 | cinfo.regn = dssdev->phy.dsi.div.regn; |
2990 | cinfo.regm = dssdev->phy.dsi.div.regm; | 3326 | cinfo.regm = dssdev->phy.dsi.div.regm; |
2991 | cinfo.regm3 = dssdev->phy.dsi.div.regm3; | 3327 | cinfo.regm_dispc = dssdev->phy.dsi.div.regm_dispc; |
2992 | cinfo.regm4 = dssdev->phy.dsi.div.regm4; | 3328 | cinfo.regm_dsi = dssdev->phy.dsi.div.regm_dsi; |
2993 | r = dsi_calc_clock_rates(dssdev, &cinfo); | 3329 | r = dsi_calc_clock_rates(dssdev, &cinfo); |
2994 | if (r) { | 3330 | if (r) { |
2995 | DSSERR("Failed to calc dsi clocks\n"); | 3331 | DSSERR("Failed to calc dsi clocks\n"); |
@@ -3011,7 +3347,7 @@ static int dsi_configure_dispc_clocks(struct omap_dss_device *dssdev) | |||
3011 | int r; | 3347 | int r; |
3012 | unsigned long long fck; | 3348 | unsigned long long fck; |
3013 | 3349 | ||
3014 | fck = dsi_get_dsi1_pll_rate(); | 3350 | fck = dsi_get_pll_hsdiv_dispc_rate(); |
3015 | 3351 | ||
3016 | dispc_cinfo.lck_div = dssdev->phy.dsi.div.lck_div; | 3352 | dispc_cinfo.lck_div = dssdev->phy.dsi.div.lck_div; |
3017 | dispc_cinfo.pck_div = dssdev->phy.dsi.div.pck_div; | 3353 | dispc_cinfo.pck_div = dssdev->phy.dsi.div.pck_div; |
@@ -3045,8 +3381,8 @@ static int dsi_display_init_dsi(struct omap_dss_device *dssdev) | |||
3045 | if (r) | 3381 | if (r) |
3046 | goto err1; | 3382 | goto err1; |
3047 | 3383 | ||
3048 | dss_select_dispc_clk_source(DSS_SRC_DSI1_PLL_FCLK); | 3384 | dss_select_dispc_clk_source(DSS_CLK_SRC_DSI_PLL_HSDIV_DISPC); |
3049 | dss_select_dsi_clk_source(DSS_SRC_DSI2_PLL_FCLK); | 3385 | dss_select_dsi_clk_source(DSS_CLK_SRC_DSI_PLL_HSDIV_DSI); |
3050 | 3386 | ||
3051 | DSSDBG("PLL OK\n"); | 3387 | DSSDBG("PLL OK\n"); |
3052 | 3388 | ||
@@ -3082,8 +3418,8 @@ static int dsi_display_init_dsi(struct omap_dss_device *dssdev) | |||
3082 | err3: | 3418 | err3: |
3083 | dsi_complexio_uninit(); | 3419 | dsi_complexio_uninit(); |
3084 | err2: | 3420 | err2: |
3085 | dss_select_dispc_clk_source(DSS_SRC_DSS1_ALWON_FCLK); | 3421 | dss_select_dispc_clk_source(DSS_CLK_SRC_FCK); |
3086 | dss_select_dsi_clk_source(DSS_SRC_DSS1_ALWON_FCLK); | 3422 | dss_select_dsi_clk_source(DSS_CLK_SRC_FCK); |
3087 | err1: | 3423 | err1: |
3088 | dsi_pll_uninit(); | 3424 | dsi_pll_uninit(); |
3089 | err0: | 3425 | err0: |
@@ -3099,8 +3435,8 @@ static void dsi_display_uninit_dsi(struct omap_dss_device *dssdev) | |||
3099 | dsi_vc_enable(2, 0); | 3435 | dsi_vc_enable(2, 0); |
3100 | dsi_vc_enable(3, 0); | 3436 | dsi_vc_enable(3, 0); |
3101 | 3437 | ||
3102 | dss_select_dispc_clk_source(DSS_SRC_DSS1_ALWON_FCLK); | 3438 | dss_select_dispc_clk_source(DSS_CLK_SRC_FCK); |
3103 | dss_select_dsi_clk_source(DSS_SRC_DSS1_ALWON_FCLK); | 3439 | dss_select_dsi_clk_source(DSS_CLK_SRC_FCK); |
3104 | dsi_complexio_uninit(); | 3440 | dsi_complexio_uninit(); |
3105 | dsi_pll_uninit(); | 3441 | dsi_pll_uninit(); |
3106 | } | 3442 | } |
@@ -3220,29 +3556,107 @@ int dsi_init_display(struct omap_dss_device *dssdev) | |||
3220 | dssdev->caps = OMAP_DSS_DISPLAY_CAP_MANUAL_UPDATE | | 3556 | dssdev->caps = OMAP_DSS_DISPLAY_CAP_MANUAL_UPDATE | |
3221 | OMAP_DSS_DISPLAY_CAP_TEAR_ELIM; | 3557 | OMAP_DSS_DISPLAY_CAP_TEAR_ELIM; |
3222 | 3558 | ||
3223 | dsi.vc[0].dssdev = dssdev; | 3559 | if (dsi.vdds_dsi_reg == NULL) { |
3224 | dsi.vc[1].dssdev = dssdev; | 3560 | struct regulator *vdds_dsi; |
3561 | |||
3562 | vdds_dsi = regulator_get(&dsi.pdev->dev, "vdds_dsi"); | ||
3563 | |||
3564 | if (IS_ERR(vdds_dsi)) { | ||
3565 | DSSERR("can't get VDDS_DSI regulator\n"); | ||
3566 | return PTR_ERR(vdds_dsi); | ||
3567 | } | ||
3568 | |||
3569 | dsi.vdds_dsi_reg = vdds_dsi; | ||
3570 | } | ||
3225 | 3571 | ||
3226 | return 0; | 3572 | return 0; |
3227 | } | 3573 | } |
3228 | 3574 | ||
3229 | void dsi_wait_dsi1_pll_active(void) | 3575 | int omap_dsi_request_vc(struct omap_dss_device *dssdev, int *channel) |
3576 | { | ||
3577 | int i; | ||
3578 | |||
3579 | for (i = 0; i < ARRAY_SIZE(dsi.vc); i++) { | ||
3580 | if (!dsi.vc[i].dssdev) { | ||
3581 | dsi.vc[i].dssdev = dssdev; | ||
3582 | *channel = i; | ||
3583 | return 0; | ||
3584 | } | ||
3585 | } | ||
3586 | |||
3587 | DSSERR("cannot get VC for display %s", dssdev->name); | ||
3588 | return -ENOSPC; | ||
3589 | } | ||
3590 | EXPORT_SYMBOL(omap_dsi_request_vc); | ||
3591 | |||
3592 | int omap_dsi_set_vc_id(struct omap_dss_device *dssdev, int channel, int vc_id) | ||
3593 | { | ||
3594 | if (vc_id < 0 || vc_id > 3) { | ||
3595 | DSSERR("VC ID out of range\n"); | ||
3596 | return -EINVAL; | ||
3597 | } | ||
3598 | |||
3599 | if (channel < 0 || channel > 3) { | ||
3600 | DSSERR("Virtual Channel out of range\n"); | ||
3601 | return -EINVAL; | ||
3602 | } | ||
3603 | |||
3604 | if (dsi.vc[channel].dssdev != dssdev) { | ||
3605 | DSSERR("Virtual Channel not allocated to display %s\n", | ||
3606 | dssdev->name); | ||
3607 | return -EINVAL; | ||
3608 | } | ||
3609 | |||
3610 | dsi.vc[channel].vc_id = vc_id; | ||
3611 | |||
3612 | return 0; | ||
3613 | } | ||
3614 | EXPORT_SYMBOL(omap_dsi_set_vc_id); | ||
3615 | |||
3616 | void omap_dsi_release_vc(struct omap_dss_device *dssdev, int channel) | ||
3617 | { | ||
3618 | if ((channel >= 0 && channel <= 3) && | ||
3619 | dsi.vc[channel].dssdev == dssdev) { | ||
3620 | dsi.vc[channel].dssdev = NULL; | ||
3621 | dsi.vc[channel].vc_id = 0; | ||
3622 | } | ||
3623 | } | ||
3624 | EXPORT_SYMBOL(omap_dsi_release_vc); | ||
3625 | |||
3626 | void dsi_wait_pll_hsdiv_dispc_active(void) | ||
3230 | { | 3627 | { |
3231 | if (wait_for_bit_change(DSI_PLL_STATUS, 7, 1) != 1) | 3628 | if (wait_for_bit_change(DSI_PLL_STATUS, 7, 1) != 1) |
3232 | DSSERR("DSI1 PLL clock not active\n"); | 3629 | DSSERR("%s (%s) not active\n", |
3630 | dss_get_generic_clk_source_name(DSS_CLK_SRC_DSI_PLL_HSDIV_DISPC), | ||
3631 | dss_feat_get_clk_source_name(DSS_CLK_SRC_DSI_PLL_HSDIV_DISPC)); | ||
3233 | } | 3632 | } |
3234 | 3633 | ||
3235 | void dsi_wait_dsi2_pll_active(void) | 3634 | void dsi_wait_pll_hsdiv_dsi_active(void) |
3236 | { | 3635 | { |
3237 | if (wait_for_bit_change(DSI_PLL_STATUS, 8, 1) != 1) | 3636 | if (wait_for_bit_change(DSI_PLL_STATUS, 8, 1) != 1) |
3238 | DSSERR("DSI2 PLL clock not active\n"); | 3637 | DSSERR("%s (%s) not active\n", |
3638 | dss_get_generic_clk_source_name(DSS_CLK_SRC_DSI_PLL_HSDIV_DSI), | ||
3639 | dss_feat_get_clk_source_name(DSS_CLK_SRC_DSI_PLL_HSDIV_DSI)); | ||
3640 | } | ||
3641 | |||
3642 | static void dsi_calc_clock_param_ranges(void) | ||
3643 | { | ||
3644 | dsi.regn_max = dss_feat_get_param_max(FEAT_PARAM_DSIPLL_REGN); | ||
3645 | dsi.regm_max = dss_feat_get_param_max(FEAT_PARAM_DSIPLL_REGM); | ||
3646 | dsi.regm_dispc_max = dss_feat_get_param_max(FEAT_PARAM_DSIPLL_REGM_DISPC); | ||
3647 | dsi.regm_dsi_max = dss_feat_get_param_max(FEAT_PARAM_DSIPLL_REGM_DSI); | ||
3648 | dsi.fint_min = dss_feat_get_param_min(FEAT_PARAM_DSIPLL_FINT); | ||
3649 | dsi.fint_max = dss_feat_get_param_max(FEAT_PARAM_DSIPLL_FINT); | ||
3650 | dsi.lpdiv_max = dss_feat_get_param_max(FEAT_PARAM_DSIPLL_LPDIV); | ||
3239 | } | 3651 | } |
3240 | 3652 | ||
3241 | int dsi_init(struct platform_device *pdev) | 3653 | static int dsi_init(struct platform_device *pdev) |
3242 | { | 3654 | { |
3243 | u32 rev; | 3655 | u32 rev; |
3244 | int r; | 3656 | int r, i; |
3657 | struct resource *dsi_mem; | ||
3245 | 3658 | ||
3659 | spin_lock_init(&dsi.irq_lock); | ||
3246 | spin_lock_init(&dsi.errors_lock); | 3660 | spin_lock_init(&dsi.errors_lock); |
3247 | dsi.errors = 0; | 3661 | dsi.errors = 0; |
3248 | 3662 | ||
@@ -3251,8 +3665,6 @@ int dsi_init(struct platform_device *pdev) | |||
3251 | dsi.irq_stats.last_reset = jiffies; | 3665 | dsi.irq_stats.last_reset = jiffies; |
3252 | #endif | 3666 | #endif |
3253 | 3667 | ||
3254 | init_completion(&dsi.bta_completion); | ||
3255 | |||
3256 | mutex_init(&dsi.lock); | 3668 | mutex_init(&dsi.lock); |
3257 | sema_init(&dsi.bus_lock, 1); | 3669 | sema_init(&dsi.bus_lock, 1); |
3258 | 3670 | ||
@@ -3268,24 +3680,45 @@ int dsi_init(struct platform_device *pdev) | |||
3268 | dsi.te_timer.function = dsi_te_timeout; | 3680 | dsi.te_timer.function = dsi_te_timeout; |
3269 | dsi.te_timer.data = 0; | 3681 | dsi.te_timer.data = 0; |
3270 | #endif | 3682 | #endif |
3271 | dsi.base = ioremap(DSI_BASE, DSI_SZ_REGS); | 3683 | dsi_mem = platform_get_resource(dsi.pdev, IORESOURCE_MEM, 0); |
3684 | if (!dsi_mem) { | ||
3685 | DSSERR("can't get IORESOURCE_MEM DSI\n"); | ||
3686 | r = -EINVAL; | ||
3687 | goto err1; | ||
3688 | } | ||
3689 | dsi.base = ioremap(dsi_mem->start, resource_size(dsi_mem)); | ||
3272 | if (!dsi.base) { | 3690 | if (!dsi.base) { |
3273 | DSSERR("can't ioremap DSI\n"); | 3691 | DSSERR("can't ioremap DSI\n"); |
3274 | r = -ENOMEM; | 3692 | r = -ENOMEM; |
3275 | goto err1; | 3693 | goto err1; |
3276 | } | 3694 | } |
3695 | dsi.irq = platform_get_irq(dsi.pdev, 0); | ||
3696 | if (dsi.irq < 0) { | ||
3697 | DSSERR("platform_get_irq failed\n"); | ||
3698 | r = -ENODEV; | ||
3699 | goto err2; | ||
3700 | } | ||
3277 | 3701 | ||
3278 | dsi.vdds_dsi_reg = dss_get_vdds_dsi(); | 3702 | r = request_irq(dsi.irq, omap_dsi_irq_handler, IRQF_SHARED, |
3279 | if (IS_ERR(dsi.vdds_dsi_reg)) { | 3703 | "OMAP DSI1", dsi.pdev); |
3280 | DSSERR("can't get VDDS_DSI regulator\n"); | 3704 | if (r < 0) { |
3281 | r = PTR_ERR(dsi.vdds_dsi_reg); | 3705 | DSSERR("request_irq failed\n"); |
3282 | goto err2; | 3706 | goto err2; |
3283 | } | 3707 | } |
3284 | 3708 | ||
3709 | /* DSI VCs initialization */ | ||
3710 | for (i = 0; i < ARRAY_SIZE(dsi.vc); i++) { | ||
3711 | dsi.vc[i].mode = DSI_VC_MODE_L4; | ||
3712 | dsi.vc[i].dssdev = NULL; | ||
3713 | dsi.vc[i].vc_id = 0; | ||
3714 | } | ||
3715 | |||
3716 | dsi_calc_clock_param_ranges(); | ||
3717 | |||
3285 | enable_clocks(1); | 3718 | enable_clocks(1); |
3286 | 3719 | ||
3287 | rev = dsi_read_reg(DSI_REVISION); | 3720 | rev = dsi_read_reg(DSI_REVISION); |
3288 | printk(KERN_INFO "OMAP DSI rev %d.%d\n", | 3721 | dev_dbg(&pdev->dev, "OMAP DSI rev %d.%d\n", |
3289 | FLD_GET(rev, 7, 4), FLD_GET(rev, 3, 0)); | 3722 | FLD_GET(rev, 7, 4), FLD_GET(rev, 3, 0)); |
3290 | 3723 | ||
3291 | enable_clocks(0); | 3724 | enable_clocks(0); |
@@ -3298,8 +3731,14 @@ err1: | |||
3298 | return r; | 3731 | return r; |
3299 | } | 3732 | } |
3300 | 3733 | ||
3301 | void dsi_exit(void) | 3734 | static void dsi_exit(void) |
3302 | { | 3735 | { |
3736 | if (dsi.vdds_dsi_reg != NULL) { | ||
3737 | regulator_put(dsi.vdds_dsi_reg); | ||
3738 | dsi.vdds_dsi_reg = NULL; | ||
3739 | } | ||
3740 | |||
3741 | free_irq(dsi.irq, dsi.pdev); | ||
3303 | iounmap(dsi.base); | 3742 | iounmap(dsi.base); |
3304 | 3743 | ||
3305 | destroy_workqueue(dsi.workqueue); | 3744 | destroy_workqueue(dsi.workqueue); |
@@ -3307,3 +3746,41 @@ void dsi_exit(void) | |||
3307 | DSSDBG("omap_dsi_exit\n"); | 3746 | DSSDBG("omap_dsi_exit\n"); |
3308 | } | 3747 | } |
3309 | 3748 | ||
3749 | /* DSI1 HW IP initialisation */ | ||
3750 | static int omap_dsi1hw_probe(struct platform_device *pdev) | ||
3751 | { | ||
3752 | int r; | ||
3753 | dsi.pdev = pdev; | ||
3754 | r = dsi_init(pdev); | ||
3755 | if (r) { | ||
3756 | DSSERR("Failed to initialize DSI\n"); | ||
3757 | goto err_dsi; | ||
3758 | } | ||
3759 | err_dsi: | ||
3760 | return r; | ||
3761 | } | ||
3762 | |||
3763 | static int omap_dsi1hw_remove(struct platform_device *pdev) | ||
3764 | { | ||
3765 | dsi_exit(); | ||
3766 | return 0; | ||
3767 | } | ||
3768 | |||
3769 | static struct platform_driver omap_dsi1hw_driver = { | ||
3770 | .probe = omap_dsi1hw_probe, | ||
3771 | .remove = omap_dsi1hw_remove, | ||
3772 | .driver = { | ||
3773 | .name = "omapdss_dsi1", | ||
3774 | .owner = THIS_MODULE, | ||
3775 | }, | ||
3776 | }; | ||
3777 | |||
3778 | int dsi_init_platform_driver(void) | ||
3779 | { | ||
3780 | return platform_driver_register(&omap_dsi1hw_driver); | ||
3781 | } | ||
3782 | |||
3783 | void dsi_uninit_platform_driver(void) | ||
3784 | { | ||
3785 | return platform_driver_unregister(&omap_dsi1hw_driver); | ||
3786 | } | ||
diff --git a/drivers/video/omap2/dss/dss.c b/drivers/video/omap2/dss/dss.c index 77c3621c9171..3f1fee63c678 100644 --- a/drivers/video/omap2/dss/dss.c +++ b/drivers/video/omap2/dss/dss.c | |||
@@ -26,14 +26,13 @@ | |||
26 | #include <linux/io.h> | 26 | #include <linux/io.h> |
27 | #include <linux/err.h> | 27 | #include <linux/err.h> |
28 | #include <linux/delay.h> | 28 | #include <linux/delay.h> |
29 | #include <linux/interrupt.h> | ||
30 | #include <linux/seq_file.h> | 29 | #include <linux/seq_file.h> |
31 | #include <linux/clk.h> | 30 | #include <linux/clk.h> |
32 | 31 | ||
33 | #include <plat/display.h> | 32 | #include <plat/display.h> |
33 | #include <plat/clock.h> | ||
34 | #include "dss.h" | 34 | #include "dss.h" |
35 | 35 | #include "dss_features.h" | |
36 | #define DSS_BASE 0x48050000 | ||
37 | 36 | ||
38 | #define DSS_SZ_REGS SZ_512 | 37 | #define DSS_SZ_REGS SZ_512 |
39 | 38 | ||
@@ -59,9 +58,17 @@ struct dss_reg { | |||
59 | dss_write_reg(idx, FLD_MOD(dss_read_reg(idx), val, start, end)) | 58 | dss_write_reg(idx, FLD_MOD(dss_read_reg(idx), val, start, end)) |
60 | 59 | ||
61 | static struct { | 60 | static struct { |
61 | struct platform_device *pdev; | ||
62 | void __iomem *base; | 62 | void __iomem *base; |
63 | int ctx_id; | ||
63 | 64 | ||
64 | struct clk *dpll4_m4_ck; | 65 | struct clk *dpll4_m4_ck; |
66 | struct clk *dss_ick; | ||
67 | struct clk *dss_fck; | ||
68 | struct clk *dss_sys_clk; | ||
69 | struct clk *dss_tv_fck; | ||
70 | struct clk *dss_video_fck; | ||
71 | unsigned num_clks_enabled; | ||
65 | 72 | ||
66 | unsigned long cache_req_pck; | 73 | unsigned long cache_req_pck; |
67 | unsigned long cache_prate; | 74 | unsigned long cache_prate; |
@@ -70,10 +77,22 @@ static struct { | |||
70 | 77 | ||
71 | enum dss_clk_source dsi_clk_source; | 78 | enum dss_clk_source dsi_clk_source; |
72 | enum dss_clk_source dispc_clk_source; | 79 | enum dss_clk_source dispc_clk_source; |
80 | enum dss_clk_source lcd_clk_source[MAX_DSS_LCD_MANAGERS]; | ||
73 | 81 | ||
74 | u32 ctx[DSS_SZ_REGS / sizeof(u32)]; | 82 | u32 ctx[DSS_SZ_REGS / sizeof(u32)]; |
75 | } dss; | 83 | } dss; |
76 | 84 | ||
85 | static const char * const dss_generic_clk_source_names[] = { | ||
86 | [DSS_CLK_SRC_DSI_PLL_HSDIV_DISPC] = "DSI_PLL_HSDIV_DISPC", | ||
87 | [DSS_CLK_SRC_DSI_PLL_HSDIV_DSI] = "DSI_PLL_HSDIV_DSI", | ||
88 | [DSS_CLK_SRC_FCK] = "DSS_FCK", | ||
89 | }; | ||
90 | |||
91 | static void dss_clk_enable_all_no_ctx(void); | ||
92 | static void dss_clk_disable_all_no_ctx(void); | ||
93 | static void dss_clk_enable_no_ctx(enum dss_clock clks); | ||
94 | static void dss_clk_disable_no_ctx(enum dss_clock clks); | ||
95 | |||
77 | static int _omap_dss_wait_reset(void); | 96 | static int _omap_dss_wait_reset(void); |
78 | 97 | ||
79 | static inline void dss_write_reg(const struct dss_reg idx, u32 val) | 98 | static inline void dss_write_reg(const struct dss_reg idx, u32 val) |
@@ -99,10 +118,11 @@ void dss_save_context(void) | |||
99 | SR(SYSCONFIG); | 118 | SR(SYSCONFIG); |
100 | SR(CONTROL); | 119 | SR(CONTROL); |
101 | 120 | ||
102 | #ifdef CONFIG_OMAP2_DSS_SDI | 121 | if (dss_feat_get_supported_displays(OMAP_DSS_CHANNEL_LCD) & |
103 | SR(SDI_CONTROL); | 122 | OMAP_DISPLAY_TYPE_SDI) { |
104 | SR(PLL_CONTROL); | 123 | SR(SDI_CONTROL); |
105 | #endif | 124 | SR(PLL_CONTROL); |
125 | } | ||
106 | } | 126 | } |
107 | 127 | ||
108 | void dss_restore_context(void) | 128 | void dss_restore_context(void) |
@@ -113,10 +133,11 @@ void dss_restore_context(void) | |||
113 | RR(SYSCONFIG); | 133 | RR(SYSCONFIG); |
114 | RR(CONTROL); | 134 | RR(CONTROL); |
115 | 135 | ||
116 | #ifdef CONFIG_OMAP2_DSS_SDI | 136 | if (dss_feat_get_supported_displays(OMAP_DSS_CHANNEL_LCD) & |
117 | RR(SDI_CONTROL); | 137 | OMAP_DISPLAY_TYPE_SDI) { |
118 | RR(PLL_CONTROL); | 138 | RR(SDI_CONTROL); |
119 | #endif | 139 | RR(PLL_CONTROL); |
140 | } | ||
120 | } | 141 | } |
121 | 142 | ||
122 | #undef SR | 143 | #undef SR |
@@ -209,66 +230,96 @@ void dss_sdi_disable(void) | |||
209 | REG_FLD_MOD(DSS_PLL_CONTROL, 0, 18, 18); /* SDI_PLL_SYSRESET */ | 230 | REG_FLD_MOD(DSS_PLL_CONTROL, 0, 18, 18); /* SDI_PLL_SYSRESET */ |
210 | } | 231 | } |
211 | 232 | ||
233 | const char *dss_get_generic_clk_source_name(enum dss_clk_source clk_src) | ||
234 | { | ||
235 | return dss_generic_clk_source_names[clk_src]; | ||
236 | } | ||
237 | |||
212 | void dss_dump_clocks(struct seq_file *s) | 238 | void dss_dump_clocks(struct seq_file *s) |
213 | { | 239 | { |
214 | unsigned long dpll4_ck_rate; | 240 | unsigned long dpll4_ck_rate; |
215 | unsigned long dpll4_m4_ck_rate; | 241 | unsigned long dpll4_m4_ck_rate; |
242 | const char *fclk_name, *fclk_real_name; | ||
243 | unsigned long fclk_rate; | ||
216 | 244 | ||
217 | dss_clk_enable(DSS_CLK_ICK | DSS_CLK_FCK1); | 245 | dss_clk_enable(DSS_CLK_ICK | DSS_CLK_FCK); |
218 | |||
219 | dpll4_ck_rate = clk_get_rate(clk_get_parent(dss.dpll4_m4_ck)); | ||
220 | dpll4_m4_ck_rate = clk_get_rate(dss.dpll4_m4_ck); | ||
221 | 246 | ||
222 | seq_printf(s, "- DSS -\n"); | 247 | seq_printf(s, "- DSS -\n"); |
223 | 248 | ||
224 | seq_printf(s, "dpll4_ck %lu\n", dpll4_ck_rate); | 249 | fclk_name = dss_get_generic_clk_source_name(DSS_CLK_SRC_FCK); |
250 | fclk_real_name = dss_feat_get_clk_source_name(DSS_CLK_SRC_FCK); | ||
251 | fclk_rate = dss_clk_get_rate(DSS_CLK_FCK); | ||
225 | 252 | ||
226 | if (cpu_is_omap3630()) | 253 | if (dss.dpll4_m4_ck) { |
227 | seq_printf(s, "dss1_alwon_fclk = %lu / %lu = %lu\n", | 254 | dpll4_ck_rate = clk_get_rate(clk_get_parent(dss.dpll4_m4_ck)); |
228 | dpll4_ck_rate, | 255 | dpll4_m4_ck_rate = clk_get_rate(dss.dpll4_m4_ck); |
229 | dpll4_ck_rate / dpll4_m4_ck_rate, | 256 | |
230 | dss_clk_get_rate(DSS_CLK_FCK1)); | 257 | seq_printf(s, "dpll4_ck %lu\n", dpll4_ck_rate); |
231 | else | ||
232 | seq_printf(s, "dss1_alwon_fclk = %lu / %lu * 2 = %lu\n", | ||
233 | dpll4_ck_rate, | ||
234 | dpll4_ck_rate / dpll4_m4_ck_rate, | ||
235 | dss_clk_get_rate(DSS_CLK_FCK1)); | ||
236 | 258 | ||
237 | dss_clk_disable(DSS_CLK_ICK | DSS_CLK_FCK1); | 259 | if (cpu_is_omap3630() || cpu_is_omap44xx()) |
260 | seq_printf(s, "%s (%s) = %lu / %lu = %lu\n", | ||
261 | fclk_name, fclk_real_name, | ||
262 | dpll4_ck_rate, | ||
263 | dpll4_ck_rate / dpll4_m4_ck_rate, | ||
264 | fclk_rate); | ||
265 | else | ||
266 | seq_printf(s, "%s (%s) = %lu / %lu * 2 = %lu\n", | ||
267 | fclk_name, fclk_real_name, | ||
268 | dpll4_ck_rate, | ||
269 | dpll4_ck_rate / dpll4_m4_ck_rate, | ||
270 | fclk_rate); | ||
271 | } else { | ||
272 | seq_printf(s, "%s (%s) = %lu\n", | ||
273 | fclk_name, fclk_real_name, | ||
274 | fclk_rate); | ||
275 | } | ||
276 | |||
277 | dss_clk_disable(DSS_CLK_ICK | DSS_CLK_FCK); | ||
238 | } | 278 | } |
239 | 279 | ||
240 | void dss_dump_regs(struct seq_file *s) | 280 | void dss_dump_regs(struct seq_file *s) |
241 | { | 281 | { |
242 | #define DUMPREG(r) seq_printf(s, "%-35s %08x\n", #r, dss_read_reg(r)) | 282 | #define DUMPREG(r) seq_printf(s, "%-35s %08x\n", #r, dss_read_reg(r)) |
243 | 283 | ||
244 | dss_clk_enable(DSS_CLK_ICK | DSS_CLK_FCK1); | 284 | dss_clk_enable(DSS_CLK_ICK | DSS_CLK_FCK); |
245 | 285 | ||
246 | DUMPREG(DSS_REVISION); | 286 | DUMPREG(DSS_REVISION); |
247 | DUMPREG(DSS_SYSCONFIG); | 287 | DUMPREG(DSS_SYSCONFIG); |
248 | DUMPREG(DSS_SYSSTATUS); | 288 | DUMPREG(DSS_SYSSTATUS); |
249 | DUMPREG(DSS_IRQSTATUS); | 289 | DUMPREG(DSS_IRQSTATUS); |
250 | DUMPREG(DSS_CONTROL); | 290 | DUMPREG(DSS_CONTROL); |
251 | DUMPREG(DSS_SDI_CONTROL); | ||
252 | DUMPREG(DSS_PLL_CONTROL); | ||
253 | DUMPREG(DSS_SDI_STATUS); | ||
254 | 291 | ||
255 | dss_clk_disable(DSS_CLK_ICK | DSS_CLK_FCK1); | 292 | if (dss_feat_get_supported_displays(OMAP_DSS_CHANNEL_LCD) & |
293 | OMAP_DISPLAY_TYPE_SDI) { | ||
294 | DUMPREG(DSS_SDI_CONTROL); | ||
295 | DUMPREG(DSS_PLL_CONTROL); | ||
296 | DUMPREG(DSS_SDI_STATUS); | ||
297 | } | ||
298 | |||
299 | dss_clk_disable(DSS_CLK_ICK | DSS_CLK_FCK); | ||
256 | #undef DUMPREG | 300 | #undef DUMPREG |
257 | } | 301 | } |
258 | 302 | ||
259 | void dss_select_dispc_clk_source(enum dss_clk_source clk_src) | 303 | void dss_select_dispc_clk_source(enum dss_clk_source clk_src) |
260 | { | 304 | { |
261 | int b; | 305 | int b; |
306 | u8 start, end; | ||
307 | |||
308 | switch (clk_src) { | ||
309 | case DSS_CLK_SRC_FCK: | ||
310 | b = 0; | ||
311 | break; | ||
312 | case DSS_CLK_SRC_DSI_PLL_HSDIV_DISPC: | ||
313 | b = 1; | ||
314 | dsi_wait_pll_hsdiv_dispc_active(); | ||
315 | break; | ||
316 | default: | ||
317 | BUG(); | ||
318 | } | ||
262 | 319 | ||
263 | BUG_ON(clk_src != DSS_SRC_DSI1_PLL_FCLK && | 320 | dss_feat_get_reg_field(FEAT_REG_DISPC_CLK_SWITCH, &start, &end); |
264 | clk_src != DSS_SRC_DSS1_ALWON_FCLK); | ||
265 | |||
266 | b = clk_src == DSS_SRC_DSS1_ALWON_FCLK ? 0 : 1; | ||
267 | |||
268 | if (clk_src == DSS_SRC_DSI1_PLL_FCLK) | ||
269 | dsi_wait_dsi1_pll_active(); | ||
270 | 321 | ||
271 | REG_FLD_MOD(DSS_CONTROL, b, 0, 0); /* DISPC_CLK_SWITCH */ | 322 | REG_FLD_MOD(DSS_CONTROL, b, start, end); /* DISPC_CLK_SWITCH */ |
272 | 323 | ||
273 | dss.dispc_clk_source = clk_src; | 324 | dss.dispc_clk_source = clk_src; |
274 | } | 325 | } |
@@ -277,19 +328,51 @@ void dss_select_dsi_clk_source(enum dss_clk_source clk_src) | |||
277 | { | 328 | { |
278 | int b; | 329 | int b; |
279 | 330 | ||
280 | BUG_ON(clk_src != DSS_SRC_DSI2_PLL_FCLK && | 331 | switch (clk_src) { |
281 | clk_src != DSS_SRC_DSS1_ALWON_FCLK); | 332 | case DSS_CLK_SRC_FCK: |
282 | 333 | b = 0; | |
283 | b = clk_src == DSS_SRC_DSS1_ALWON_FCLK ? 0 : 1; | 334 | break; |
284 | 335 | case DSS_CLK_SRC_DSI_PLL_HSDIV_DSI: | |
285 | if (clk_src == DSS_SRC_DSI2_PLL_FCLK) | 336 | b = 1; |
286 | dsi_wait_dsi2_pll_active(); | 337 | dsi_wait_pll_hsdiv_dsi_active(); |
338 | break; | ||
339 | default: | ||
340 | BUG(); | ||
341 | } | ||
287 | 342 | ||
288 | REG_FLD_MOD(DSS_CONTROL, b, 1, 1); /* DSI_CLK_SWITCH */ | 343 | REG_FLD_MOD(DSS_CONTROL, b, 1, 1); /* DSI_CLK_SWITCH */ |
289 | 344 | ||
290 | dss.dsi_clk_source = clk_src; | 345 | dss.dsi_clk_source = clk_src; |
291 | } | 346 | } |
292 | 347 | ||
348 | void dss_select_lcd_clk_source(enum omap_channel channel, | ||
349 | enum dss_clk_source clk_src) | ||
350 | { | ||
351 | int b, ix, pos; | ||
352 | |||
353 | if (!dss_has_feature(FEAT_LCD_CLK_SRC)) | ||
354 | return; | ||
355 | |||
356 | switch (clk_src) { | ||
357 | case DSS_CLK_SRC_FCK: | ||
358 | b = 0; | ||
359 | break; | ||
360 | case DSS_CLK_SRC_DSI_PLL_HSDIV_DISPC: | ||
361 | BUG_ON(channel != OMAP_DSS_CHANNEL_LCD); | ||
362 | b = 1; | ||
363 | dsi_wait_pll_hsdiv_dispc_active(); | ||
364 | break; | ||
365 | default: | ||
366 | BUG(); | ||
367 | } | ||
368 | |||
369 | pos = channel == OMAP_DSS_CHANNEL_LCD ? 0 : 12; | ||
370 | REG_FLD_MOD(DSS_CONTROL, b, pos, pos); /* LCDx_CLK_SWITCH */ | ||
371 | |||
372 | ix = channel == OMAP_DSS_CHANNEL_LCD ? 0 : 1; | ||
373 | dss.lcd_clk_source[ix] = clk_src; | ||
374 | } | ||
375 | |||
293 | enum dss_clk_source dss_get_dispc_clk_source(void) | 376 | enum dss_clk_source dss_get_dispc_clk_source(void) |
294 | { | 377 | { |
295 | return dss.dispc_clk_source; | 378 | return dss.dispc_clk_source; |
@@ -300,34 +383,52 @@ enum dss_clk_source dss_get_dsi_clk_source(void) | |||
300 | return dss.dsi_clk_source; | 383 | return dss.dsi_clk_source; |
301 | } | 384 | } |
302 | 385 | ||
386 | enum dss_clk_source dss_get_lcd_clk_source(enum omap_channel channel) | ||
387 | { | ||
388 | int ix = channel == OMAP_DSS_CHANNEL_LCD ? 0 : 1; | ||
389 | return dss.lcd_clk_source[ix]; | ||
390 | } | ||
391 | |||
303 | /* calculate clock rates using dividers in cinfo */ | 392 | /* calculate clock rates using dividers in cinfo */ |
304 | int dss_calc_clock_rates(struct dss_clock_info *cinfo) | 393 | int dss_calc_clock_rates(struct dss_clock_info *cinfo) |
305 | { | 394 | { |
306 | unsigned long prate; | 395 | if (dss.dpll4_m4_ck) { |
396 | unsigned long prate; | ||
397 | u16 fck_div_max = 16; | ||
307 | 398 | ||
308 | if (cinfo->fck_div > (cpu_is_omap3630() ? 32 : 16) || | 399 | if (cpu_is_omap3630() || cpu_is_omap44xx()) |
309 | cinfo->fck_div == 0) | 400 | fck_div_max = 32; |
310 | return -EINVAL; | 401 | |
402 | if (cinfo->fck_div > fck_div_max || cinfo->fck_div == 0) | ||
403 | return -EINVAL; | ||
311 | 404 | ||
312 | prate = clk_get_rate(clk_get_parent(dss.dpll4_m4_ck)); | 405 | prate = clk_get_rate(clk_get_parent(dss.dpll4_m4_ck)); |
313 | 406 | ||
314 | cinfo->fck = prate / cinfo->fck_div; | 407 | cinfo->fck = prate / cinfo->fck_div; |
408 | } else { | ||
409 | if (cinfo->fck_div != 0) | ||
410 | return -EINVAL; | ||
411 | cinfo->fck = dss_clk_get_rate(DSS_CLK_FCK); | ||
412 | } | ||
315 | 413 | ||
316 | return 0; | 414 | return 0; |
317 | } | 415 | } |
318 | 416 | ||
319 | int dss_set_clock_div(struct dss_clock_info *cinfo) | 417 | int dss_set_clock_div(struct dss_clock_info *cinfo) |
320 | { | 418 | { |
321 | unsigned long prate; | 419 | if (dss.dpll4_m4_ck) { |
322 | int r; | 420 | unsigned long prate; |
421 | int r; | ||
323 | 422 | ||
324 | if (cpu_is_omap34xx()) { | ||
325 | prate = clk_get_rate(clk_get_parent(dss.dpll4_m4_ck)); | 423 | prate = clk_get_rate(clk_get_parent(dss.dpll4_m4_ck)); |
326 | DSSDBG("dpll4_m4 = %ld\n", prate); | 424 | DSSDBG("dpll4_m4 = %ld\n", prate); |
327 | 425 | ||
328 | r = clk_set_rate(dss.dpll4_m4_ck, prate / cinfo->fck_div); | 426 | r = clk_set_rate(dss.dpll4_m4_ck, prate / cinfo->fck_div); |
329 | if (r) | 427 | if (r) |
330 | return r; | 428 | return r; |
429 | } else { | ||
430 | if (cinfo->fck_div != 0) | ||
431 | return -EINVAL; | ||
331 | } | 432 | } |
332 | 433 | ||
333 | DSSDBG("fck = %ld (%d)\n", cinfo->fck, cinfo->fck_div); | 434 | DSSDBG("fck = %ld (%d)\n", cinfo->fck, cinfo->fck_div); |
@@ -337,12 +438,14 @@ int dss_set_clock_div(struct dss_clock_info *cinfo) | |||
337 | 438 | ||
338 | int dss_get_clock_div(struct dss_clock_info *cinfo) | 439 | int dss_get_clock_div(struct dss_clock_info *cinfo) |
339 | { | 440 | { |
340 | cinfo->fck = dss_clk_get_rate(DSS_CLK_FCK1); | 441 | cinfo->fck = dss_clk_get_rate(DSS_CLK_FCK); |
341 | 442 | ||
342 | if (cpu_is_omap34xx()) { | 443 | if (dss.dpll4_m4_ck) { |
343 | unsigned long prate; | 444 | unsigned long prate; |
445 | |||
344 | prate = clk_get_rate(clk_get_parent(dss.dpll4_m4_ck)); | 446 | prate = clk_get_rate(clk_get_parent(dss.dpll4_m4_ck)); |
345 | if (cpu_is_omap3630()) | 447 | |
448 | if (cpu_is_omap3630() || cpu_is_omap44xx()) | ||
346 | cinfo->fck_div = prate / (cinfo->fck); | 449 | cinfo->fck_div = prate / (cinfo->fck); |
347 | else | 450 | else |
348 | cinfo->fck_div = prate / (cinfo->fck / 2); | 451 | cinfo->fck_div = prate / (cinfo->fck / 2); |
@@ -355,7 +458,7 @@ int dss_get_clock_div(struct dss_clock_info *cinfo) | |||
355 | 458 | ||
356 | unsigned long dss_get_dpll4_rate(void) | 459 | unsigned long dss_get_dpll4_rate(void) |
357 | { | 460 | { |
358 | if (cpu_is_omap34xx()) | 461 | if (dss.dpll4_m4_ck) |
359 | return clk_get_rate(clk_get_parent(dss.dpll4_m4_ck)); | 462 | return clk_get_rate(clk_get_parent(dss.dpll4_m4_ck)); |
360 | else | 463 | else |
361 | return 0; | 464 | return 0; |
@@ -369,16 +472,18 @@ int dss_calc_clock_div(bool is_tft, unsigned long req_pck, | |||
369 | struct dss_clock_info best_dss; | 472 | struct dss_clock_info best_dss; |
370 | struct dispc_clock_info best_dispc; | 473 | struct dispc_clock_info best_dispc; |
371 | 474 | ||
372 | unsigned long fck; | 475 | unsigned long fck, max_dss_fck; |
373 | 476 | ||
374 | u16 fck_div; | 477 | u16 fck_div, fck_div_max = 16; |
375 | 478 | ||
376 | int match = 0; | 479 | int match = 0; |
377 | int min_fck_per_pck; | 480 | int min_fck_per_pck; |
378 | 481 | ||
379 | prate = dss_get_dpll4_rate(); | 482 | prate = dss_get_dpll4_rate(); |
380 | 483 | ||
381 | fck = dss_clk_get_rate(DSS_CLK_FCK1); | 484 | max_dss_fck = dss_feat_get_param_max(FEAT_PARAM_DSS_FCK); |
485 | |||
486 | fck = dss_clk_get_rate(DSS_CLK_FCK); | ||
382 | if (req_pck == dss.cache_req_pck && | 487 | if (req_pck == dss.cache_req_pck && |
383 | ((cpu_is_omap34xx() && prate == dss.cache_prate) || | 488 | ((cpu_is_omap34xx() && prate == dss.cache_prate) || |
384 | dss.cache_dss_cinfo.fck == fck)) { | 489 | dss.cache_dss_cinfo.fck == fck)) { |
@@ -391,7 +496,7 @@ int dss_calc_clock_div(bool is_tft, unsigned long req_pck, | |||
391 | min_fck_per_pck = CONFIG_OMAP2_DSS_MIN_FCK_PER_PCK; | 496 | min_fck_per_pck = CONFIG_OMAP2_DSS_MIN_FCK_PER_PCK; |
392 | 497 | ||
393 | if (min_fck_per_pck && | 498 | if (min_fck_per_pck && |
394 | req_pck * min_fck_per_pck > DISPC_MAX_FCK) { | 499 | req_pck * min_fck_per_pck > max_dss_fck) { |
395 | DSSERR("Requested pixel clock not possible with the current " | 500 | DSSERR("Requested pixel clock not possible with the current " |
396 | "OMAP2_DSS_MIN_FCK_PER_PCK setting. Turning " | 501 | "OMAP2_DSS_MIN_FCK_PER_PCK setting. Turning " |
397 | "the constraint off.\n"); | 502 | "the constraint off.\n"); |
@@ -402,10 +507,10 @@ retry: | |||
402 | memset(&best_dss, 0, sizeof(best_dss)); | 507 | memset(&best_dss, 0, sizeof(best_dss)); |
403 | memset(&best_dispc, 0, sizeof(best_dispc)); | 508 | memset(&best_dispc, 0, sizeof(best_dispc)); |
404 | 509 | ||
405 | if (cpu_is_omap24xx()) { | 510 | if (dss.dpll4_m4_ck == NULL) { |
406 | struct dispc_clock_info cur_dispc; | 511 | struct dispc_clock_info cur_dispc; |
407 | /* XXX can we change the clock on omap2? */ | 512 | /* XXX can we change the clock on omap2? */ |
408 | fck = dss_clk_get_rate(DSS_CLK_FCK1); | 513 | fck = dss_clk_get_rate(DSS_CLK_FCK); |
409 | fck_div = 1; | 514 | fck_div = 1; |
410 | 515 | ||
411 | dispc_find_clk_divs(is_tft, req_pck, fck, &cur_dispc); | 516 | dispc_find_clk_divs(is_tft, req_pck, fck, &cur_dispc); |
@@ -417,17 +522,19 @@ retry: | |||
417 | best_dispc = cur_dispc; | 522 | best_dispc = cur_dispc; |
418 | 523 | ||
419 | goto found; | 524 | goto found; |
420 | } else if (cpu_is_omap34xx()) { | 525 | } else { |
421 | for (fck_div = (cpu_is_omap3630() ? 32 : 16); | 526 | if (cpu_is_omap3630() || cpu_is_omap44xx()) |
422 | fck_div > 0; --fck_div) { | 527 | fck_div_max = 32; |
528 | |||
529 | for (fck_div = fck_div_max; fck_div > 0; --fck_div) { | ||
423 | struct dispc_clock_info cur_dispc; | 530 | struct dispc_clock_info cur_dispc; |
424 | 531 | ||
425 | if (cpu_is_omap3630()) | 532 | if (fck_div_max == 32) |
426 | fck = prate / fck_div; | 533 | fck = prate / fck_div; |
427 | else | 534 | else |
428 | fck = prate / fck_div * 2; | 535 | fck = prate / fck_div * 2; |
429 | 536 | ||
430 | if (fck > DISPC_MAX_FCK) | 537 | if (fck > max_dss_fck) |
431 | continue; | 538 | continue; |
432 | 539 | ||
433 | if (min_fck_per_pck && | 540 | if (min_fck_per_pck && |
@@ -450,8 +557,6 @@ retry: | |||
450 | goto found; | 557 | goto found; |
451 | } | 558 | } |
452 | } | 559 | } |
453 | } else { | ||
454 | BUG(); | ||
455 | } | 560 | } |
456 | 561 | ||
457 | found: | 562 | found: |
@@ -482,31 +587,6 @@ found: | |||
482 | return 0; | 587 | return 0; |
483 | } | 588 | } |
484 | 589 | ||
485 | |||
486 | |||
487 | static irqreturn_t dss_irq_handler_omap2(int irq, void *arg) | ||
488 | { | ||
489 | dispc_irq_handler(); | ||
490 | |||
491 | return IRQ_HANDLED; | ||
492 | } | ||
493 | |||
494 | static irqreturn_t dss_irq_handler_omap3(int irq, void *arg) | ||
495 | { | ||
496 | u32 irqstatus; | ||
497 | |||
498 | irqstatus = dss_read_reg(DSS_IRQSTATUS); | ||
499 | |||
500 | if (irqstatus & (1<<0)) /* DISPC_IRQ */ | ||
501 | dispc_irq_handler(); | ||
502 | #ifdef CONFIG_OMAP2_DSS_DSI | ||
503 | if (irqstatus & (1<<1)) /* DSI_IRQ */ | ||
504 | dsi_irq_handler(); | ||
505 | #endif | ||
506 | |||
507 | return IRQ_HANDLED; | ||
508 | } | ||
509 | |||
510 | static int _omap_dss_wait_reset(void) | 590 | static int _omap_dss_wait_reset(void) |
511 | { | 591 | { |
512 | int t = 0; | 592 | int t = 0; |
@@ -549,34 +629,45 @@ void dss_set_dac_pwrdn_bgz(bool enable) | |||
549 | REG_FLD_MOD(DSS_CONTROL, enable, 5, 5); /* DAC Power-Down Control */ | 629 | REG_FLD_MOD(DSS_CONTROL, enable, 5, 5); /* DAC Power-Down Control */ |
550 | } | 630 | } |
551 | 631 | ||
552 | int dss_init(bool skip_init) | 632 | void dss_select_hdmi_venc_clk_source(enum dss_hdmi_venc_clk_source_select hdmi) |
633 | { | ||
634 | REG_FLD_MOD(DSS_CONTROL, hdmi, 15, 15); /* VENC_HDMI_SWITCH */ | ||
635 | } | ||
636 | |||
637 | static int dss_init(void) | ||
553 | { | 638 | { |
554 | int r; | 639 | int r; |
555 | u32 rev; | 640 | u32 rev; |
641 | struct resource *dss_mem; | ||
642 | struct clk *dpll4_m4_ck; | ||
556 | 643 | ||
557 | dss.base = ioremap(DSS_BASE, DSS_SZ_REGS); | 644 | dss_mem = platform_get_resource(dss.pdev, IORESOURCE_MEM, 0); |
645 | if (!dss_mem) { | ||
646 | DSSERR("can't get IORESOURCE_MEM DSS\n"); | ||
647 | r = -EINVAL; | ||
648 | goto fail0; | ||
649 | } | ||
650 | dss.base = ioremap(dss_mem->start, resource_size(dss_mem)); | ||
558 | if (!dss.base) { | 651 | if (!dss.base) { |
559 | DSSERR("can't ioremap DSS\n"); | 652 | DSSERR("can't ioremap DSS\n"); |
560 | r = -ENOMEM; | 653 | r = -ENOMEM; |
561 | goto fail0; | 654 | goto fail0; |
562 | } | 655 | } |
563 | 656 | ||
564 | if (!skip_init) { | 657 | /* disable LCD and DIGIT output. This seems to fix the synclost |
565 | /* disable LCD and DIGIT output. This seems to fix the synclost | 658 | * problem that we get, if the bootloader starts the DSS and |
566 | * problem that we get, if the bootloader starts the DSS and | 659 | * the kernel resets it */ |
567 | * the kernel resets it */ | 660 | omap_writel(omap_readl(0x48050440) & ~0x3, 0x48050440); |
568 | omap_writel(omap_readl(0x48050440) & ~0x3, 0x48050440); | ||
569 | 661 | ||
570 | /* We need to wait here a bit, otherwise we sometimes start to | 662 | /* We need to wait here a bit, otherwise we sometimes start to |
571 | * get synclost errors, and after that only power cycle will | 663 | * get synclost errors, and after that only power cycle will |
572 | * restore DSS functionality. I have no idea why this happens. | 664 | * restore DSS functionality. I have no idea why this happens. |
573 | * And we have to wait _before_ resetting the DSS, but after | 665 | * And we have to wait _before_ resetting the DSS, but after |
574 | * enabling clocks. | 666 | * enabling clocks. |
575 | */ | 667 | */ |
576 | msleep(50); | 668 | msleep(50); |
577 | 669 | ||
578 | _omap_dss_reset(); | 670 | _omap_dss_reset(); |
579 | } | ||
580 | 671 | ||
581 | /* autoidle */ | 672 | /* autoidle */ |
582 | REG_FLD_MOD(DSS_SYSCONFIG, 1, 0, 0); | 673 | REG_FLD_MOD(DSS_SYSCONFIG, 1, 0, 0); |
@@ -589,29 +680,30 @@ int dss_init(bool skip_init) | |||
589 | REG_FLD_MOD(DSS_CONTROL, 1, 3, 3); /* venc clock 4x enable */ | 680 | REG_FLD_MOD(DSS_CONTROL, 1, 3, 3); /* venc clock 4x enable */ |
590 | REG_FLD_MOD(DSS_CONTROL, 0, 2, 2); /* venc clock mode = normal */ | 681 | REG_FLD_MOD(DSS_CONTROL, 0, 2, 2); /* venc clock mode = normal */ |
591 | #endif | 682 | #endif |
592 | |||
593 | r = request_irq(INT_24XX_DSS_IRQ, | ||
594 | cpu_is_omap24xx() | ||
595 | ? dss_irq_handler_omap2 | ||
596 | : dss_irq_handler_omap3, | ||
597 | 0, "OMAP DSS", NULL); | ||
598 | |||
599 | if (r < 0) { | ||
600 | DSSERR("omap2 dss: request_irq failed\n"); | ||
601 | goto fail1; | ||
602 | } | ||
603 | |||
604 | if (cpu_is_omap34xx()) { | 683 | if (cpu_is_omap34xx()) { |
605 | dss.dpll4_m4_ck = clk_get(NULL, "dpll4_m4_ck"); | 684 | dpll4_m4_ck = clk_get(NULL, "dpll4_m4_ck"); |
606 | if (IS_ERR(dss.dpll4_m4_ck)) { | 685 | if (IS_ERR(dpll4_m4_ck)) { |
607 | DSSERR("Failed to get dpll4_m4_ck\n"); | 686 | DSSERR("Failed to get dpll4_m4_ck\n"); |
608 | r = PTR_ERR(dss.dpll4_m4_ck); | 687 | r = PTR_ERR(dpll4_m4_ck); |
609 | goto fail2; | 688 | goto fail1; |
610 | } | 689 | } |
690 | } else if (cpu_is_omap44xx()) { | ||
691 | dpll4_m4_ck = clk_get(NULL, "dpll_per_m5x2_ck"); | ||
692 | if (IS_ERR(dpll4_m4_ck)) { | ||
693 | DSSERR("Failed to get dpll4_m4_ck\n"); | ||
694 | r = PTR_ERR(dpll4_m4_ck); | ||
695 | goto fail1; | ||
696 | } | ||
697 | } else { /* omap24xx */ | ||
698 | dpll4_m4_ck = NULL; | ||
611 | } | 699 | } |
612 | 700 | ||
613 | dss.dsi_clk_source = DSS_SRC_DSS1_ALWON_FCLK; | 701 | dss.dpll4_m4_ck = dpll4_m4_ck; |
614 | dss.dispc_clk_source = DSS_SRC_DSS1_ALWON_FCLK; | 702 | |
703 | dss.dsi_clk_source = DSS_CLK_SRC_FCK; | ||
704 | dss.dispc_clk_source = DSS_CLK_SRC_FCK; | ||
705 | dss.lcd_clk_source[0] = DSS_CLK_SRC_FCK; | ||
706 | dss.lcd_clk_source[1] = DSS_CLK_SRC_FCK; | ||
615 | 707 | ||
616 | dss_save_context(); | 708 | dss_save_context(); |
617 | 709 | ||
@@ -621,21 +713,416 @@ int dss_init(bool skip_init) | |||
621 | 713 | ||
622 | return 0; | 714 | return 0; |
623 | 715 | ||
624 | fail2: | ||
625 | free_irq(INT_24XX_DSS_IRQ, NULL); | ||
626 | fail1: | 716 | fail1: |
627 | iounmap(dss.base); | 717 | iounmap(dss.base); |
628 | fail0: | 718 | fail0: |
629 | return r; | 719 | return r; |
630 | } | 720 | } |
631 | 721 | ||
632 | void dss_exit(void) | 722 | static void dss_exit(void) |
633 | { | 723 | { |
634 | if (cpu_is_omap34xx()) | 724 | if (dss.dpll4_m4_ck) |
635 | clk_put(dss.dpll4_m4_ck); | 725 | clk_put(dss.dpll4_m4_ck); |
636 | 726 | ||
637 | free_irq(INT_24XX_DSS_IRQ, NULL); | ||
638 | |||
639 | iounmap(dss.base); | 727 | iounmap(dss.base); |
640 | } | 728 | } |
641 | 729 | ||
730 | /* CONTEXT */ | ||
731 | static int dss_get_ctx_id(void) | ||
732 | { | ||
733 | struct omap_display_platform_data *pdata = dss.pdev->dev.platform_data; | ||
734 | int r; | ||
735 | |||
736 | if (!pdata->board_data->get_last_off_on_transaction_id) | ||
737 | return 0; | ||
738 | r = pdata->board_data->get_last_off_on_transaction_id(&dss.pdev->dev); | ||
739 | if (r < 0) { | ||
740 | dev_err(&dss.pdev->dev, "getting transaction ID failed, " | ||
741 | "will force context restore\n"); | ||
742 | r = -1; | ||
743 | } | ||
744 | return r; | ||
745 | } | ||
746 | |||
747 | int dss_need_ctx_restore(void) | ||
748 | { | ||
749 | int id = dss_get_ctx_id(); | ||
750 | |||
751 | if (id < 0 || id != dss.ctx_id) { | ||
752 | DSSDBG("ctx id %d -> id %d\n", | ||
753 | dss.ctx_id, id); | ||
754 | dss.ctx_id = id; | ||
755 | return 1; | ||
756 | } else { | ||
757 | return 0; | ||
758 | } | ||
759 | } | ||
760 | |||
761 | static void save_all_ctx(void) | ||
762 | { | ||
763 | DSSDBG("save context\n"); | ||
764 | |||
765 | dss_clk_enable_no_ctx(DSS_CLK_ICK | DSS_CLK_FCK); | ||
766 | |||
767 | dss_save_context(); | ||
768 | dispc_save_context(); | ||
769 | #ifdef CONFIG_OMAP2_DSS_DSI | ||
770 | dsi_save_context(); | ||
771 | #endif | ||
772 | |||
773 | dss_clk_disable_no_ctx(DSS_CLK_ICK | DSS_CLK_FCK); | ||
774 | } | ||
775 | |||
776 | static void restore_all_ctx(void) | ||
777 | { | ||
778 | DSSDBG("restore context\n"); | ||
779 | |||
780 | dss_clk_enable_all_no_ctx(); | ||
781 | |||
782 | dss_restore_context(); | ||
783 | dispc_restore_context(); | ||
784 | #ifdef CONFIG_OMAP2_DSS_DSI | ||
785 | dsi_restore_context(); | ||
786 | #endif | ||
787 | |||
788 | dss_clk_disable_all_no_ctx(); | ||
789 | } | ||
790 | |||
791 | static int dss_get_clock(struct clk **clock, const char *clk_name) | ||
792 | { | ||
793 | struct clk *clk; | ||
794 | |||
795 | clk = clk_get(&dss.pdev->dev, clk_name); | ||
796 | |||
797 | if (IS_ERR(clk)) { | ||
798 | DSSERR("can't get clock %s", clk_name); | ||
799 | return PTR_ERR(clk); | ||
800 | } | ||
801 | |||
802 | *clock = clk; | ||
803 | |||
804 | DSSDBG("clk %s, rate %ld\n", clk_name, clk_get_rate(clk)); | ||
805 | |||
806 | return 0; | ||
807 | } | ||
808 | |||
809 | static int dss_get_clocks(void) | ||
810 | { | ||
811 | int r; | ||
812 | struct omap_display_platform_data *pdata = dss.pdev->dev.platform_data; | ||
813 | |||
814 | dss.dss_ick = NULL; | ||
815 | dss.dss_fck = NULL; | ||
816 | dss.dss_sys_clk = NULL; | ||
817 | dss.dss_tv_fck = NULL; | ||
818 | dss.dss_video_fck = NULL; | ||
819 | |||
820 | r = dss_get_clock(&dss.dss_ick, "ick"); | ||
821 | if (r) | ||
822 | goto err; | ||
823 | |||
824 | r = dss_get_clock(&dss.dss_fck, "fck"); | ||
825 | if (r) | ||
826 | goto err; | ||
827 | |||
828 | if (!pdata->opt_clock_available) { | ||
829 | r = -ENODEV; | ||
830 | goto err; | ||
831 | } | ||
832 | |||
833 | if (pdata->opt_clock_available("sys_clk")) { | ||
834 | r = dss_get_clock(&dss.dss_sys_clk, "sys_clk"); | ||
835 | if (r) | ||
836 | goto err; | ||
837 | } | ||
838 | |||
839 | if (pdata->opt_clock_available("tv_clk")) { | ||
840 | r = dss_get_clock(&dss.dss_tv_fck, "tv_clk"); | ||
841 | if (r) | ||
842 | goto err; | ||
843 | } | ||
844 | |||
845 | if (pdata->opt_clock_available("video_clk")) { | ||
846 | r = dss_get_clock(&dss.dss_video_fck, "video_clk"); | ||
847 | if (r) | ||
848 | goto err; | ||
849 | } | ||
850 | |||
851 | return 0; | ||
852 | |||
853 | err: | ||
854 | if (dss.dss_ick) | ||
855 | clk_put(dss.dss_ick); | ||
856 | if (dss.dss_fck) | ||
857 | clk_put(dss.dss_fck); | ||
858 | if (dss.dss_sys_clk) | ||
859 | clk_put(dss.dss_sys_clk); | ||
860 | if (dss.dss_tv_fck) | ||
861 | clk_put(dss.dss_tv_fck); | ||
862 | if (dss.dss_video_fck) | ||
863 | clk_put(dss.dss_video_fck); | ||
864 | |||
865 | return r; | ||
866 | } | ||
867 | |||
868 | static void dss_put_clocks(void) | ||
869 | { | ||
870 | if (dss.dss_video_fck) | ||
871 | clk_put(dss.dss_video_fck); | ||
872 | if (dss.dss_tv_fck) | ||
873 | clk_put(dss.dss_tv_fck); | ||
874 | if (dss.dss_sys_clk) | ||
875 | clk_put(dss.dss_sys_clk); | ||
876 | clk_put(dss.dss_fck); | ||
877 | clk_put(dss.dss_ick); | ||
878 | } | ||
879 | |||
880 | unsigned long dss_clk_get_rate(enum dss_clock clk) | ||
881 | { | ||
882 | switch (clk) { | ||
883 | case DSS_CLK_ICK: | ||
884 | return clk_get_rate(dss.dss_ick); | ||
885 | case DSS_CLK_FCK: | ||
886 | return clk_get_rate(dss.dss_fck); | ||
887 | case DSS_CLK_SYSCK: | ||
888 | return clk_get_rate(dss.dss_sys_clk); | ||
889 | case DSS_CLK_TVFCK: | ||
890 | return clk_get_rate(dss.dss_tv_fck); | ||
891 | case DSS_CLK_VIDFCK: | ||
892 | return clk_get_rate(dss.dss_video_fck); | ||
893 | } | ||
894 | |||
895 | BUG(); | ||
896 | return 0; | ||
897 | } | ||
898 | |||
899 | static unsigned count_clk_bits(enum dss_clock clks) | ||
900 | { | ||
901 | unsigned num_clks = 0; | ||
902 | |||
903 | if (clks & DSS_CLK_ICK) | ||
904 | ++num_clks; | ||
905 | if (clks & DSS_CLK_FCK) | ||
906 | ++num_clks; | ||
907 | if (clks & DSS_CLK_SYSCK) | ||
908 | ++num_clks; | ||
909 | if (clks & DSS_CLK_TVFCK) | ||
910 | ++num_clks; | ||
911 | if (clks & DSS_CLK_VIDFCK) | ||
912 | ++num_clks; | ||
913 | |||
914 | return num_clks; | ||
915 | } | ||
916 | |||
917 | static void dss_clk_enable_no_ctx(enum dss_clock clks) | ||
918 | { | ||
919 | unsigned num_clks = count_clk_bits(clks); | ||
920 | |||
921 | if (clks & DSS_CLK_ICK) | ||
922 | clk_enable(dss.dss_ick); | ||
923 | if (clks & DSS_CLK_FCK) | ||
924 | clk_enable(dss.dss_fck); | ||
925 | if ((clks & DSS_CLK_SYSCK) && dss.dss_sys_clk) | ||
926 | clk_enable(dss.dss_sys_clk); | ||
927 | if ((clks & DSS_CLK_TVFCK) && dss.dss_tv_fck) | ||
928 | clk_enable(dss.dss_tv_fck); | ||
929 | if ((clks & DSS_CLK_VIDFCK) && dss.dss_video_fck) | ||
930 | clk_enable(dss.dss_video_fck); | ||
931 | |||
932 | dss.num_clks_enabled += num_clks; | ||
933 | } | ||
934 | |||
935 | void dss_clk_enable(enum dss_clock clks) | ||
936 | { | ||
937 | bool check_ctx = dss.num_clks_enabled == 0; | ||
938 | |||
939 | dss_clk_enable_no_ctx(clks); | ||
940 | |||
941 | /* | ||
942 | * HACK: On omap4 the registers may not be accessible right after | ||
943 | * enabling the clocks. At some point this will be handled by | ||
944 | * pm_runtime, but for the time begin this should make things work. | ||
945 | */ | ||
946 | if (cpu_is_omap44xx() && check_ctx) | ||
947 | udelay(10); | ||
948 | |||
949 | if (check_ctx && cpu_is_omap34xx() && dss_need_ctx_restore()) | ||
950 | restore_all_ctx(); | ||
951 | } | ||
952 | |||
953 | static void dss_clk_disable_no_ctx(enum dss_clock clks) | ||
954 | { | ||
955 | unsigned num_clks = count_clk_bits(clks); | ||
956 | |||
957 | if (clks & DSS_CLK_ICK) | ||
958 | clk_disable(dss.dss_ick); | ||
959 | if (clks & DSS_CLK_FCK) | ||
960 | clk_disable(dss.dss_fck); | ||
961 | if ((clks & DSS_CLK_SYSCK) && dss.dss_sys_clk) | ||
962 | clk_disable(dss.dss_sys_clk); | ||
963 | if ((clks & DSS_CLK_TVFCK) && dss.dss_tv_fck) | ||
964 | clk_disable(dss.dss_tv_fck); | ||
965 | if ((clks & DSS_CLK_VIDFCK) && dss.dss_video_fck) | ||
966 | clk_disable(dss.dss_video_fck); | ||
967 | |||
968 | dss.num_clks_enabled -= num_clks; | ||
969 | } | ||
970 | |||
971 | void dss_clk_disable(enum dss_clock clks) | ||
972 | { | ||
973 | if (cpu_is_omap34xx()) { | ||
974 | unsigned num_clks = count_clk_bits(clks); | ||
975 | |||
976 | BUG_ON(dss.num_clks_enabled < num_clks); | ||
977 | |||
978 | if (dss.num_clks_enabled == num_clks) | ||
979 | save_all_ctx(); | ||
980 | } | ||
981 | |||
982 | dss_clk_disable_no_ctx(clks); | ||
983 | } | ||
984 | |||
985 | static void dss_clk_enable_all_no_ctx(void) | ||
986 | { | ||
987 | enum dss_clock clks; | ||
988 | |||
989 | clks = DSS_CLK_ICK | DSS_CLK_FCK | DSS_CLK_SYSCK | DSS_CLK_TVFCK; | ||
990 | if (cpu_is_omap34xx()) | ||
991 | clks |= DSS_CLK_VIDFCK; | ||
992 | dss_clk_enable_no_ctx(clks); | ||
993 | } | ||
994 | |||
995 | static void dss_clk_disable_all_no_ctx(void) | ||
996 | { | ||
997 | enum dss_clock clks; | ||
998 | |||
999 | clks = DSS_CLK_ICK | DSS_CLK_FCK | DSS_CLK_SYSCK | DSS_CLK_TVFCK; | ||
1000 | if (cpu_is_omap34xx()) | ||
1001 | clks |= DSS_CLK_VIDFCK; | ||
1002 | dss_clk_disable_no_ctx(clks); | ||
1003 | } | ||
1004 | |||
1005 | #if defined(CONFIG_DEBUG_FS) && defined(CONFIG_OMAP2_DSS_DEBUG_SUPPORT) | ||
1006 | /* CLOCKS */ | ||
1007 | static void core_dump_clocks(struct seq_file *s) | ||
1008 | { | ||
1009 | int i; | ||
1010 | struct clk *clocks[5] = { | ||
1011 | dss.dss_ick, | ||
1012 | dss.dss_fck, | ||
1013 | dss.dss_sys_clk, | ||
1014 | dss.dss_tv_fck, | ||
1015 | dss.dss_video_fck | ||
1016 | }; | ||
1017 | |||
1018 | seq_printf(s, "- CORE -\n"); | ||
1019 | |||
1020 | seq_printf(s, "internal clk count\t\t%u\n", dss.num_clks_enabled); | ||
1021 | |||
1022 | for (i = 0; i < 5; i++) { | ||
1023 | if (!clocks[i]) | ||
1024 | continue; | ||
1025 | seq_printf(s, "%-15s\t%lu\t%d\n", | ||
1026 | clocks[i]->name, | ||
1027 | clk_get_rate(clocks[i]), | ||
1028 | clocks[i]->usecount); | ||
1029 | } | ||
1030 | } | ||
1031 | #endif /* defined(CONFIG_DEBUG_FS) && defined(CONFIG_OMAP2_DSS_DEBUG_SUPPORT) */ | ||
1032 | |||
1033 | /* DEBUGFS */ | ||
1034 | #if defined(CONFIG_DEBUG_FS) && defined(CONFIG_OMAP2_DSS_DEBUG_SUPPORT) | ||
1035 | void dss_debug_dump_clocks(struct seq_file *s) | ||
1036 | { | ||
1037 | core_dump_clocks(s); | ||
1038 | dss_dump_clocks(s); | ||
1039 | dispc_dump_clocks(s); | ||
1040 | #ifdef CONFIG_OMAP2_DSS_DSI | ||
1041 | dsi_dump_clocks(s); | ||
1042 | #endif | ||
1043 | } | ||
1044 | #endif | ||
1045 | |||
1046 | |||
1047 | /* DSS HW IP initialisation */ | ||
1048 | static int omap_dsshw_probe(struct platform_device *pdev) | ||
1049 | { | ||
1050 | int r; | ||
1051 | |||
1052 | dss.pdev = pdev; | ||
1053 | |||
1054 | r = dss_get_clocks(); | ||
1055 | if (r) | ||
1056 | goto err_clocks; | ||
1057 | |||
1058 | dss_clk_enable_all_no_ctx(); | ||
1059 | |||
1060 | dss.ctx_id = dss_get_ctx_id(); | ||
1061 | DSSDBG("initial ctx id %u\n", dss.ctx_id); | ||
1062 | |||
1063 | r = dss_init(); | ||
1064 | if (r) { | ||
1065 | DSSERR("Failed to initialize DSS\n"); | ||
1066 | goto err_dss; | ||
1067 | } | ||
1068 | |||
1069 | r = dpi_init(); | ||
1070 | if (r) { | ||
1071 | DSSERR("Failed to initialize DPI\n"); | ||
1072 | goto err_dpi; | ||
1073 | } | ||
1074 | |||
1075 | r = sdi_init(); | ||
1076 | if (r) { | ||
1077 | DSSERR("Failed to initialize SDI\n"); | ||
1078 | goto err_sdi; | ||
1079 | } | ||
1080 | |||
1081 | dss_clk_disable_all_no_ctx(); | ||
1082 | return 0; | ||
1083 | err_sdi: | ||
1084 | dpi_exit(); | ||
1085 | err_dpi: | ||
1086 | dss_exit(); | ||
1087 | err_dss: | ||
1088 | dss_clk_disable_all_no_ctx(); | ||
1089 | dss_put_clocks(); | ||
1090 | err_clocks: | ||
1091 | return r; | ||
1092 | } | ||
1093 | |||
1094 | static int omap_dsshw_remove(struct platform_device *pdev) | ||
1095 | { | ||
1096 | |||
1097 | dss_exit(); | ||
1098 | |||
1099 | /* | ||
1100 | * As part of hwmod changes, DSS is not the only controller of dss | ||
1101 | * clocks; hwmod framework itself will also enable clocks during hwmod | ||
1102 | * init for dss, and autoidle is set in h/w for DSS. Hence, there's no | ||
1103 | * need to disable clocks if their usecounts > 1. | ||
1104 | */ | ||
1105 | WARN_ON(dss.num_clks_enabled > 0); | ||
1106 | |||
1107 | dss_put_clocks(); | ||
1108 | return 0; | ||
1109 | } | ||
1110 | |||
1111 | static struct platform_driver omap_dsshw_driver = { | ||
1112 | .probe = omap_dsshw_probe, | ||
1113 | .remove = omap_dsshw_remove, | ||
1114 | .driver = { | ||
1115 | .name = "omapdss_dss", | ||
1116 | .owner = THIS_MODULE, | ||
1117 | }, | ||
1118 | }; | ||
1119 | |||
1120 | int dss_init_platform_driver(void) | ||
1121 | { | ||
1122 | return platform_driver_register(&omap_dsshw_driver); | ||
1123 | } | ||
1124 | |||
1125 | void dss_uninit_platform_driver(void) | ||
1126 | { | ||
1127 | return platform_driver_unregister(&omap_dsshw_driver); | ||
1128 | } | ||
diff --git a/drivers/video/omap2/dss/dss.h b/drivers/video/omap2/dss/dss.h index b394951120ac..c2f582bb19c0 100644 --- a/drivers/video/omap2/dss/dss.h +++ b/drivers/video/omap2/dss/dss.h | |||
@@ -97,8 +97,6 @@ extern unsigned int dss_debug; | |||
97 | #define FLD_MOD(orig, val, start, end) \ | 97 | #define FLD_MOD(orig, val, start, end) \ |
98 | (((orig) & ~FLD_MASK(start, end)) | FLD_VAL(val, start, end)) | 98 | (((orig) & ~FLD_MASK(start, end)) | FLD_VAL(val, start, end)) |
99 | 99 | ||
100 | #define DISPC_MAX_FCK 173000000 | ||
101 | |||
102 | enum omap_burst_size { | 100 | enum omap_burst_size { |
103 | OMAP_DSS_BURST_4x32 = 0, | 101 | OMAP_DSS_BURST_4x32 = 0, |
104 | OMAP_DSS_BURST_8x32 = 1, | 102 | OMAP_DSS_BURST_8x32 = 1, |
@@ -112,17 +110,25 @@ enum omap_parallel_interface_mode { | |||
112 | }; | 110 | }; |
113 | 111 | ||
114 | enum dss_clock { | 112 | enum dss_clock { |
115 | DSS_CLK_ICK = 1 << 0, | 113 | DSS_CLK_ICK = 1 << 0, /* DSS_L3_ICLK and DSS_L4_ICLK */ |
116 | DSS_CLK_FCK1 = 1 << 1, | 114 | DSS_CLK_FCK = 1 << 1, /* DSS1_ALWON_FCLK */ |
117 | DSS_CLK_FCK2 = 1 << 2, | 115 | DSS_CLK_SYSCK = 1 << 2, /* DSS2_ALWON_FCLK */ |
118 | DSS_CLK_54M = 1 << 3, | 116 | DSS_CLK_TVFCK = 1 << 3, /* DSS_TV_FCLK */ |
119 | DSS_CLK_96M = 1 << 4, | 117 | DSS_CLK_VIDFCK = 1 << 4, /* DSS_96M_FCLK*/ |
120 | }; | 118 | }; |
121 | 119 | ||
122 | enum dss_clk_source { | 120 | enum dss_clk_source { |
123 | DSS_SRC_DSI1_PLL_FCLK, | 121 | DSS_CLK_SRC_DSI_PLL_HSDIV_DISPC, /* OMAP3: DSI1_PLL_FCLK |
124 | DSS_SRC_DSI2_PLL_FCLK, | 122 | * OMAP4: PLL1_CLK1 */ |
125 | DSS_SRC_DSS1_ALWON_FCLK, | 123 | DSS_CLK_SRC_DSI_PLL_HSDIV_DSI, /* OMAP3: DSI2_PLL_FCLK |
124 | * OMAP4: PLL1_CLK2 */ | ||
125 | DSS_CLK_SRC_FCK, /* OMAP2/3: DSS1_ALWON_FCLK | ||
126 | * OMAP4: DSS_FCLK */ | ||
127 | }; | ||
128 | |||
129 | enum dss_hdmi_venc_clk_source_select { | ||
130 | DSS_VENC_TV_CLK = 0, | ||
131 | DSS_HDMI_M_PCLK = 1, | ||
126 | }; | 132 | }; |
127 | 133 | ||
128 | struct dss_clock_info { | 134 | struct dss_clock_info { |
@@ -148,36 +154,42 @@ struct dsi_clock_info { | |||
148 | unsigned long fint; | 154 | unsigned long fint; |
149 | unsigned long clkin4ddr; | 155 | unsigned long clkin4ddr; |
150 | unsigned long clkin; | 156 | unsigned long clkin; |
151 | unsigned long dsi1_pll_fclk; | 157 | unsigned long dsi_pll_hsdiv_dispc_clk; /* OMAP3: DSI1_PLL_CLK |
152 | unsigned long dsi2_pll_fclk; | 158 | * OMAP4: PLLx_CLK1 */ |
153 | 159 | unsigned long dsi_pll_hsdiv_dsi_clk; /* OMAP3: DSI2_PLL_CLK | |
160 | * OMAP4: PLLx_CLK2 */ | ||
154 | unsigned long lp_clk; | 161 | unsigned long lp_clk; |
155 | 162 | ||
156 | /* dividers */ | 163 | /* dividers */ |
157 | u16 regn; | 164 | u16 regn; |
158 | u16 regm; | 165 | u16 regm; |
159 | u16 regm3; | 166 | u16 regm_dispc; /* OMAP3: REGM3 |
160 | u16 regm4; | 167 | * OMAP4: REGM4 */ |
161 | 168 | u16 regm_dsi; /* OMAP3: REGM4 | |
169 | * OMAP4: REGM5 */ | ||
162 | u16 lp_clk_div; | 170 | u16 lp_clk_div; |
163 | 171 | ||
164 | u8 highfreq; | 172 | u8 highfreq; |
165 | bool use_dss2_fck; | 173 | bool use_sys_clk; |
174 | }; | ||
175 | |||
176 | /* HDMI PLL structure */ | ||
177 | struct hdmi_pll_info { | ||
178 | u16 regn; | ||
179 | u16 regm; | ||
180 | u32 regmf; | ||
181 | u16 regm2; | ||
182 | u16 regsd; | ||
183 | u16 dcofreq; | ||
166 | }; | 184 | }; |
167 | 185 | ||
168 | struct seq_file; | 186 | struct seq_file; |
169 | struct platform_device; | 187 | struct platform_device; |
170 | 188 | ||
171 | /* core */ | 189 | /* core */ |
172 | void dss_clk_enable(enum dss_clock clks); | ||
173 | void dss_clk_disable(enum dss_clock clks); | ||
174 | unsigned long dss_clk_get_rate(enum dss_clock clk); | ||
175 | int dss_need_ctx_restore(void); | ||
176 | void dss_dump_clocks(struct seq_file *s); | ||
177 | struct bus_type *dss_get_bus(void); | 190 | struct bus_type *dss_get_bus(void); |
178 | struct regulator *dss_get_vdds_dsi(void); | 191 | struct regulator *dss_get_vdds_dsi(void); |
179 | struct regulator *dss_get_vdds_sdi(void); | 192 | struct regulator *dss_get_vdds_sdi(void); |
180 | struct regulator *dss_get_vdda_dac(void); | ||
181 | 193 | ||
182 | /* display */ | 194 | /* display */ |
183 | int dss_suspend_all_devices(void); | 195 | int dss_suspend_all_devices(void); |
@@ -214,13 +226,23 @@ void dss_overlay_setup_l4_manager(struct omap_overlay_manager *mgr); | |||
214 | void dss_recheck_connections(struct omap_dss_device *dssdev, bool force); | 226 | void dss_recheck_connections(struct omap_dss_device *dssdev, bool force); |
215 | 227 | ||
216 | /* DSS */ | 228 | /* DSS */ |
217 | int dss_init(bool skip_init); | 229 | int dss_init_platform_driver(void); |
218 | void dss_exit(void); | 230 | void dss_uninit_platform_driver(void); |
219 | 231 | ||
232 | void dss_select_hdmi_venc_clk_source(enum dss_hdmi_venc_clk_source_select); | ||
220 | void dss_save_context(void); | 233 | void dss_save_context(void); |
221 | void dss_restore_context(void); | 234 | void dss_restore_context(void); |
235 | void dss_clk_enable(enum dss_clock clks); | ||
236 | void dss_clk_disable(enum dss_clock clks); | ||
237 | unsigned long dss_clk_get_rate(enum dss_clock clk); | ||
238 | int dss_need_ctx_restore(void); | ||
239 | const char *dss_get_generic_clk_source_name(enum dss_clk_source clk_src); | ||
240 | void dss_dump_clocks(struct seq_file *s); | ||
222 | 241 | ||
223 | void dss_dump_regs(struct seq_file *s); | 242 | void dss_dump_regs(struct seq_file *s); |
243 | #if defined(CONFIG_DEBUG_FS) && defined(CONFIG_OMAP2_DSS_DEBUG_SUPPORT) | ||
244 | void dss_debug_dump_clocks(struct seq_file *s); | ||
245 | #endif | ||
224 | 246 | ||
225 | void dss_sdi_init(u8 datapairs); | 247 | void dss_sdi_init(u8 datapairs); |
226 | int dss_sdi_enable(void); | 248 | int dss_sdi_enable(void); |
@@ -228,8 +250,11 @@ void dss_sdi_disable(void); | |||
228 | 250 | ||
229 | void dss_select_dispc_clk_source(enum dss_clk_source clk_src); | 251 | void dss_select_dispc_clk_source(enum dss_clk_source clk_src); |
230 | void dss_select_dsi_clk_source(enum dss_clk_source clk_src); | 252 | void dss_select_dsi_clk_source(enum dss_clk_source clk_src); |
253 | void dss_select_lcd_clk_source(enum omap_channel channel, | ||
254 | enum dss_clk_source clk_src); | ||
231 | enum dss_clk_source dss_get_dispc_clk_source(void); | 255 | enum dss_clk_source dss_get_dispc_clk_source(void); |
232 | enum dss_clk_source dss_get_dsi_clk_source(void); | 256 | enum dss_clk_source dss_get_dsi_clk_source(void); |
257 | enum dss_clk_source dss_get_lcd_clk_source(enum omap_channel channel); | ||
233 | 258 | ||
234 | void dss_set_venc_output(enum omap_dss_venc_type type); | 259 | void dss_set_venc_output(enum omap_dss_venc_type type); |
235 | void dss_set_dac_pwrdn_bgz(bool enable); | 260 | void dss_set_dac_pwrdn_bgz(bool enable); |
@@ -244,11 +269,11 @@ int dss_calc_clock_div(bool is_tft, unsigned long req_pck, | |||
244 | 269 | ||
245 | /* SDI */ | 270 | /* SDI */ |
246 | #ifdef CONFIG_OMAP2_DSS_SDI | 271 | #ifdef CONFIG_OMAP2_DSS_SDI |
247 | int sdi_init(bool skip_init); | 272 | int sdi_init(void); |
248 | void sdi_exit(void); | 273 | void sdi_exit(void); |
249 | int sdi_init_display(struct omap_dss_device *display); | 274 | int sdi_init_display(struct omap_dss_device *display); |
250 | #else | 275 | #else |
251 | static inline int sdi_init(bool skip_init) | 276 | static inline int sdi_init(void) |
252 | { | 277 | { |
253 | return 0; | 278 | return 0; |
254 | } | 279 | } |
@@ -259,8 +284,8 @@ static inline void sdi_exit(void) | |||
259 | 284 | ||
260 | /* DSI */ | 285 | /* DSI */ |
261 | #ifdef CONFIG_OMAP2_DSS_DSI | 286 | #ifdef CONFIG_OMAP2_DSS_DSI |
262 | int dsi_init(struct platform_device *pdev); | 287 | int dsi_init_platform_driver(void); |
263 | void dsi_exit(void); | 288 | void dsi_uninit_platform_driver(void); |
264 | 289 | ||
265 | void dsi_dump_clocks(struct seq_file *s); | 290 | void dsi_dump_clocks(struct seq_file *s); |
266 | void dsi_dump_irqs(struct seq_file *s); | 291 | void dsi_dump_irqs(struct seq_file *s); |
@@ -271,7 +296,7 @@ void dsi_restore_context(void); | |||
271 | 296 | ||
272 | int dsi_init_display(struct omap_dss_device *display); | 297 | int dsi_init_display(struct omap_dss_device *display); |
273 | void dsi_irq_handler(void); | 298 | void dsi_irq_handler(void); |
274 | unsigned long dsi_get_dsi1_pll_rate(void); | 299 | unsigned long dsi_get_pll_hsdiv_dispc_rate(void); |
275 | int dsi_pll_set_clock_div(struct dsi_clock_info *cinfo); | 300 | int dsi_pll_set_clock_div(struct dsi_clock_info *cinfo); |
276 | int dsi_pll_calc_clock_div_pck(bool is_tft, unsigned long req_pck, | 301 | int dsi_pll_calc_clock_div_pck(bool is_tft, unsigned long req_pck, |
277 | struct dsi_clock_info *cinfo, | 302 | struct dsi_clock_info *cinfo, |
@@ -282,31 +307,36 @@ void dsi_pll_uninit(void); | |||
282 | void dsi_get_overlay_fifo_thresholds(enum omap_plane plane, | 307 | void dsi_get_overlay_fifo_thresholds(enum omap_plane plane, |
283 | u32 fifo_size, enum omap_burst_size *burst_size, | 308 | u32 fifo_size, enum omap_burst_size *burst_size, |
284 | u32 *fifo_low, u32 *fifo_high); | 309 | u32 *fifo_low, u32 *fifo_high); |
285 | void dsi_wait_dsi1_pll_active(void); | 310 | void dsi_wait_pll_hsdiv_dispc_active(void); |
286 | void dsi_wait_dsi2_pll_active(void); | 311 | void dsi_wait_pll_hsdiv_dsi_active(void); |
287 | #else | 312 | #else |
288 | static inline int dsi_init(struct platform_device *pdev) | 313 | static inline int dsi_init_platform_driver(void) |
289 | { | 314 | { |
290 | return 0; | 315 | return 0; |
291 | } | 316 | } |
292 | static inline void dsi_exit(void) | 317 | static inline void dsi_uninit_platform_driver(void) |
293 | { | 318 | { |
294 | } | 319 | } |
295 | static inline void dsi_wait_dsi1_pll_active(void) | 320 | static inline unsigned long dsi_get_pll_hsdiv_dispc_rate(void) |
296 | { | 321 | { |
322 | WARN("%s: DSI not compiled in, returning rate as 0\n", __func__); | ||
323 | return 0; | ||
297 | } | 324 | } |
298 | static inline void dsi_wait_dsi2_pll_active(void) | 325 | static inline void dsi_wait_pll_hsdiv_dispc_active(void) |
326 | { | ||
327 | } | ||
328 | static inline void dsi_wait_pll_hsdiv_dsi_active(void) | ||
299 | { | 329 | { |
300 | } | 330 | } |
301 | #endif | 331 | #endif |
302 | 332 | ||
303 | /* DPI */ | 333 | /* DPI */ |
304 | #ifdef CONFIG_OMAP2_DSS_DPI | 334 | #ifdef CONFIG_OMAP2_DSS_DPI |
305 | int dpi_init(struct platform_device *pdev); | 335 | int dpi_init(void); |
306 | void dpi_exit(void); | 336 | void dpi_exit(void); |
307 | int dpi_init_display(struct omap_dss_device *dssdev); | 337 | int dpi_init_display(struct omap_dss_device *dssdev); |
308 | #else | 338 | #else |
309 | static inline int dpi_init(struct platform_device *pdev) | 339 | static inline int dpi_init(void) |
310 | { | 340 | { |
311 | return 0; | 341 | return 0; |
312 | } | 342 | } |
@@ -316,8 +346,8 @@ static inline void dpi_exit(void) | |||
316 | #endif | 346 | #endif |
317 | 347 | ||
318 | /* DISPC */ | 348 | /* DISPC */ |
319 | int dispc_init(void); | 349 | int dispc_init_platform_driver(void); |
320 | void dispc_exit(void); | 350 | void dispc_uninit_platform_driver(void); |
321 | void dispc_dump_clocks(struct seq_file *s); | 351 | void dispc_dump_clocks(struct seq_file *s); |
322 | void dispc_dump_irqs(struct seq_file *s); | 352 | void dispc_dump_irqs(struct seq_file *s); |
323 | void dispc_dump_regs(struct seq_file *s); | 353 | void dispc_dump_regs(struct seq_file *s); |
@@ -350,6 +380,7 @@ void dispc_set_plane_size(enum omap_plane plane, u16 width, u16 height); | |||
350 | void dispc_set_channel_out(enum omap_plane plane, | 380 | void dispc_set_channel_out(enum omap_plane plane, |
351 | enum omap_channel channel_out); | 381 | enum omap_channel channel_out); |
352 | 382 | ||
383 | void dispc_enable_gamma_table(bool enable); | ||
353 | int dispc_setup_plane(enum omap_plane plane, | 384 | int dispc_setup_plane(enum omap_plane plane, |
354 | u32 paddr, u16 screen_width, | 385 | u32 paddr, u16 screen_width, |
355 | u16 pos_x, u16 pos_y, | 386 | u16 pos_x, u16 pos_y, |
@@ -409,24 +440,50 @@ int dispc_get_clock_div(enum omap_channel channel, | |||
409 | 440 | ||
410 | /* VENC */ | 441 | /* VENC */ |
411 | #ifdef CONFIG_OMAP2_DSS_VENC | 442 | #ifdef CONFIG_OMAP2_DSS_VENC |
412 | int venc_init(struct platform_device *pdev); | 443 | int venc_init_platform_driver(void); |
413 | void venc_exit(void); | 444 | void venc_uninit_platform_driver(void); |
414 | void venc_dump_regs(struct seq_file *s); | 445 | void venc_dump_regs(struct seq_file *s); |
415 | int venc_init_display(struct omap_dss_device *display); | 446 | int venc_init_display(struct omap_dss_device *display); |
416 | #else | 447 | #else |
417 | static inline int venc_init(struct platform_device *pdev) | 448 | static inline int venc_init_platform_driver(void) |
449 | { | ||
450 | return 0; | ||
451 | } | ||
452 | static inline void venc_uninit_platform_driver(void) | ||
453 | { | ||
454 | } | ||
455 | #endif | ||
456 | |||
457 | /* HDMI */ | ||
458 | #ifdef CONFIG_OMAP4_DSS_HDMI | ||
459 | int hdmi_init_platform_driver(void); | ||
460 | void hdmi_uninit_platform_driver(void); | ||
461 | int hdmi_init_display(struct omap_dss_device *dssdev); | ||
462 | #else | ||
463 | static inline int hdmi_init_display(struct omap_dss_device *dssdev) | ||
464 | { | ||
465 | return 0; | ||
466 | } | ||
467 | static inline int hdmi_init_platform_driver(void) | ||
418 | { | 468 | { |
419 | return 0; | 469 | return 0; |
420 | } | 470 | } |
421 | static inline void venc_exit(void) | 471 | static inline void hdmi_uninit_platform_driver(void) |
422 | { | 472 | { |
423 | } | 473 | } |
424 | #endif | 474 | #endif |
475 | int omapdss_hdmi_display_enable(struct omap_dss_device *dssdev); | ||
476 | void omapdss_hdmi_display_disable(struct omap_dss_device *dssdev); | ||
477 | void omapdss_hdmi_display_set_timing(struct omap_dss_device *dssdev); | ||
478 | int omapdss_hdmi_display_check_timing(struct omap_dss_device *dssdev, | ||
479 | struct omap_video_timings *timings); | ||
480 | int hdmi_panel_init(void); | ||
481 | void hdmi_panel_exit(void); | ||
425 | 482 | ||
426 | /* RFBI */ | 483 | /* RFBI */ |
427 | #ifdef CONFIG_OMAP2_DSS_RFBI | 484 | #ifdef CONFIG_OMAP2_DSS_RFBI |
428 | int rfbi_init(void); | 485 | int rfbi_init_platform_driver(void); |
429 | void rfbi_exit(void); | 486 | void rfbi_uninit_platform_driver(void); |
430 | void rfbi_dump_regs(struct seq_file *s); | 487 | void rfbi_dump_regs(struct seq_file *s); |
431 | 488 | ||
432 | int rfbi_configure(int rfbi_module, int bpp, int lines); | 489 | int rfbi_configure(int rfbi_module, int bpp, int lines); |
@@ -437,11 +494,11 @@ void rfbi_set_timings(int rfbi_module, struct rfbi_timings *t); | |||
437 | unsigned long rfbi_get_max_tx_rate(void); | 494 | unsigned long rfbi_get_max_tx_rate(void); |
438 | int rfbi_init_display(struct omap_dss_device *display); | 495 | int rfbi_init_display(struct omap_dss_device *display); |
439 | #else | 496 | #else |
440 | static inline int rfbi_init(void) | 497 | static inline int rfbi_init_platform_driver(void) |
441 | { | 498 | { |
442 | return 0; | 499 | return 0; |
443 | } | 500 | } |
444 | static inline void rfbi_exit(void) | 501 | static inline void rfbi_uninit_platform_driver(void) |
445 | { | 502 | { |
446 | } | 503 | } |
447 | #endif | 504 | #endif |
diff --git a/drivers/video/omap2/dss/dss_features.c b/drivers/video/omap2/dss/dss_features.c index cf3ef696e141..aa1622241d0d 100644 --- a/drivers/video/omap2/dss/dss_features.c +++ b/drivers/video/omap2/dss/dss_features.c | |||
@@ -25,14 +25,18 @@ | |||
25 | #include <plat/display.h> | 25 | #include <plat/display.h> |
26 | #include <plat/cpu.h> | 26 | #include <plat/cpu.h> |
27 | 27 | ||
28 | #include "dss.h" | ||
28 | #include "dss_features.h" | 29 | #include "dss_features.h" |
29 | 30 | ||
30 | /* Defines a generic omap register field */ | 31 | /* Defines a generic omap register field */ |
31 | struct dss_reg_field { | 32 | struct dss_reg_field { |
32 | enum dss_feat_reg_field id; | ||
33 | u8 start, end; | 33 | u8 start, end; |
34 | }; | 34 | }; |
35 | 35 | ||
36 | struct dss_param_range { | ||
37 | int min, max; | ||
38 | }; | ||
39 | |||
36 | struct omap_dss_features { | 40 | struct omap_dss_features { |
37 | const struct dss_reg_field *reg_fields; | 41 | const struct dss_reg_field *reg_fields; |
38 | const int num_reg_fields; | 42 | const int num_reg_fields; |
@@ -43,29 +47,68 @@ struct omap_dss_features { | |||
43 | const int num_ovls; | 47 | const int num_ovls; |
44 | const enum omap_display_type *supported_displays; | 48 | const enum omap_display_type *supported_displays; |
45 | const enum omap_color_mode *supported_color_modes; | 49 | const enum omap_color_mode *supported_color_modes; |
50 | const char * const *clksrc_names; | ||
51 | const struct dss_param_range *dss_params; | ||
46 | }; | 52 | }; |
47 | 53 | ||
48 | /* This struct is assigned to one of the below during initialization */ | 54 | /* This struct is assigned to one of the below during initialization */ |
49 | static struct omap_dss_features *omap_current_dss_features; | 55 | static struct omap_dss_features *omap_current_dss_features; |
50 | 56 | ||
51 | static const struct dss_reg_field omap2_dss_reg_fields[] = { | 57 | static const struct dss_reg_field omap2_dss_reg_fields[] = { |
52 | { FEAT_REG_FIRHINC, 11, 0 }, | 58 | [FEAT_REG_FIRHINC] = { 11, 0 }, |
53 | { FEAT_REG_FIRVINC, 27, 16 }, | 59 | [FEAT_REG_FIRVINC] = { 27, 16 }, |
54 | { FEAT_REG_FIFOLOWTHRESHOLD, 8, 0 }, | 60 | [FEAT_REG_FIFOLOWTHRESHOLD] = { 8, 0 }, |
55 | { FEAT_REG_FIFOHIGHTHRESHOLD, 24, 16 }, | 61 | [FEAT_REG_FIFOHIGHTHRESHOLD] = { 24, 16 }, |
56 | { FEAT_REG_FIFOSIZE, 8, 0 }, | 62 | [FEAT_REG_FIFOSIZE] = { 8, 0 }, |
63 | [FEAT_REG_HORIZONTALACCU] = { 9, 0 }, | ||
64 | [FEAT_REG_VERTICALACCU] = { 25, 16 }, | ||
65 | [FEAT_REG_DISPC_CLK_SWITCH] = { 0, 0 }, | ||
66 | [FEAT_REG_DSIPLL_REGN] = { 0, 0 }, | ||
67 | [FEAT_REG_DSIPLL_REGM] = { 0, 0 }, | ||
68 | [FEAT_REG_DSIPLL_REGM_DISPC] = { 0, 0 }, | ||
69 | [FEAT_REG_DSIPLL_REGM_DSI] = { 0, 0 }, | ||
57 | }; | 70 | }; |
58 | 71 | ||
59 | static const struct dss_reg_field omap3_dss_reg_fields[] = { | 72 | static const struct dss_reg_field omap3_dss_reg_fields[] = { |
60 | { FEAT_REG_FIRHINC, 12, 0 }, | 73 | [FEAT_REG_FIRHINC] = { 12, 0 }, |
61 | { FEAT_REG_FIRVINC, 28, 16 }, | 74 | [FEAT_REG_FIRVINC] = { 28, 16 }, |
62 | { FEAT_REG_FIFOLOWTHRESHOLD, 11, 0 }, | 75 | [FEAT_REG_FIFOLOWTHRESHOLD] = { 11, 0 }, |
63 | { FEAT_REG_FIFOHIGHTHRESHOLD, 27, 16 }, | 76 | [FEAT_REG_FIFOHIGHTHRESHOLD] = { 27, 16 }, |
64 | { FEAT_REG_FIFOSIZE, 10, 0 }, | 77 | [FEAT_REG_FIFOSIZE] = { 10, 0 }, |
78 | [FEAT_REG_HORIZONTALACCU] = { 9, 0 }, | ||
79 | [FEAT_REG_VERTICALACCU] = { 25, 16 }, | ||
80 | [FEAT_REG_DISPC_CLK_SWITCH] = { 0, 0 }, | ||
81 | [FEAT_REG_DSIPLL_REGN] = { 7, 1 }, | ||
82 | [FEAT_REG_DSIPLL_REGM] = { 18, 8 }, | ||
83 | [FEAT_REG_DSIPLL_REGM_DISPC] = { 22, 19 }, | ||
84 | [FEAT_REG_DSIPLL_REGM_DSI] = { 26, 23 }, | ||
85 | }; | ||
86 | |||
87 | static const struct dss_reg_field omap4_dss_reg_fields[] = { | ||
88 | [FEAT_REG_FIRHINC] = { 12, 0 }, | ||
89 | [FEAT_REG_FIRVINC] = { 28, 16 }, | ||
90 | [FEAT_REG_FIFOLOWTHRESHOLD] = { 15, 0 }, | ||
91 | [FEAT_REG_FIFOHIGHTHRESHOLD] = { 31, 16 }, | ||
92 | [FEAT_REG_FIFOSIZE] = { 15, 0 }, | ||
93 | [FEAT_REG_HORIZONTALACCU] = { 10, 0 }, | ||
94 | [FEAT_REG_VERTICALACCU] = { 26, 16 }, | ||
95 | [FEAT_REG_DISPC_CLK_SWITCH] = { 9, 8 }, | ||
96 | [FEAT_REG_DSIPLL_REGN] = { 8, 1 }, | ||
97 | [FEAT_REG_DSIPLL_REGM] = { 20, 9 }, | ||
98 | [FEAT_REG_DSIPLL_REGM_DISPC] = { 25, 21 }, | ||
99 | [FEAT_REG_DSIPLL_REGM_DSI] = { 30, 26 }, | ||
65 | }; | 100 | }; |
66 | 101 | ||
67 | static const enum omap_display_type omap2_dss_supported_displays[] = { | 102 | static const enum omap_display_type omap2_dss_supported_displays[] = { |
68 | /* OMAP_DSS_CHANNEL_LCD */ | 103 | /* OMAP_DSS_CHANNEL_LCD */ |
104 | OMAP_DISPLAY_TYPE_DPI | OMAP_DISPLAY_TYPE_DBI, | ||
105 | |||
106 | /* OMAP_DSS_CHANNEL_DIGIT */ | ||
107 | OMAP_DISPLAY_TYPE_VENC, | ||
108 | }; | ||
109 | |||
110 | static const enum omap_display_type omap3430_dss_supported_displays[] = { | ||
111 | /* OMAP_DSS_CHANNEL_LCD */ | ||
69 | OMAP_DISPLAY_TYPE_DPI | OMAP_DISPLAY_TYPE_DBI | | 112 | OMAP_DISPLAY_TYPE_DPI | OMAP_DISPLAY_TYPE_DBI | |
70 | OMAP_DISPLAY_TYPE_SDI | OMAP_DISPLAY_TYPE_DSI, | 113 | OMAP_DISPLAY_TYPE_SDI | OMAP_DISPLAY_TYPE_DSI, |
71 | 114 | ||
@@ -73,10 +116,10 @@ static const enum omap_display_type omap2_dss_supported_displays[] = { | |||
73 | OMAP_DISPLAY_TYPE_VENC, | 116 | OMAP_DISPLAY_TYPE_VENC, |
74 | }; | 117 | }; |
75 | 118 | ||
76 | static const enum omap_display_type omap3_dss_supported_displays[] = { | 119 | static const enum omap_display_type omap3630_dss_supported_displays[] = { |
77 | /* OMAP_DSS_CHANNEL_LCD */ | 120 | /* OMAP_DSS_CHANNEL_LCD */ |
78 | OMAP_DISPLAY_TYPE_DPI | OMAP_DISPLAY_TYPE_DBI | | 121 | OMAP_DISPLAY_TYPE_DPI | OMAP_DISPLAY_TYPE_DBI | |
79 | OMAP_DISPLAY_TYPE_SDI | OMAP_DISPLAY_TYPE_DSI, | 122 | OMAP_DISPLAY_TYPE_DSI, |
80 | 123 | ||
81 | /* OMAP_DSS_CHANNEL_DIGIT */ | 124 | /* OMAP_DSS_CHANNEL_DIGIT */ |
82 | OMAP_DISPLAY_TYPE_VENC, | 125 | OMAP_DISPLAY_TYPE_VENC, |
@@ -87,7 +130,7 @@ static const enum omap_display_type omap4_dss_supported_displays[] = { | |||
87 | OMAP_DISPLAY_TYPE_DBI | OMAP_DISPLAY_TYPE_DSI, | 130 | OMAP_DISPLAY_TYPE_DBI | OMAP_DISPLAY_TYPE_DSI, |
88 | 131 | ||
89 | /* OMAP_DSS_CHANNEL_DIGIT */ | 132 | /* OMAP_DSS_CHANNEL_DIGIT */ |
90 | OMAP_DISPLAY_TYPE_VENC, | 133 | OMAP_DISPLAY_TYPE_VENC | OMAP_DISPLAY_TYPE_HDMI, |
91 | 134 | ||
92 | /* OMAP_DSS_CHANNEL_LCD2 */ | 135 | /* OMAP_DSS_CHANNEL_LCD2 */ |
93 | OMAP_DISPLAY_TYPE_DPI | OMAP_DISPLAY_TYPE_DBI | | 136 | OMAP_DISPLAY_TYPE_DPI | OMAP_DISPLAY_TYPE_DBI | |
@@ -134,6 +177,54 @@ static const enum omap_color_mode omap3_dss_supported_color_modes[] = { | |||
134 | OMAP_DSS_COLOR_RGBA32 | OMAP_DSS_COLOR_RGBX32, | 177 | OMAP_DSS_COLOR_RGBA32 | OMAP_DSS_COLOR_RGBX32, |
135 | }; | 178 | }; |
136 | 179 | ||
180 | static const char * const omap2_dss_clk_source_names[] = { | ||
181 | [DSS_CLK_SRC_DSI_PLL_HSDIV_DISPC] = "N/A", | ||
182 | [DSS_CLK_SRC_DSI_PLL_HSDIV_DSI] = "N/A", | ||
183 | [DSS_CLK_SRC_FCK] = "DSS_FCLK1", | ||
184 | }; | ||
185 | |||
186 | static const char * const omap3_dss_clk_source_names[] = { | ||
187 | [DSS_CLK_SRC_DSI_PLL_HSDIV_DISPC] = "DSI1_PLL_FCLK", | ||
188 | [DSS_CLK_SRC_DSI_PLL_HSDIV_DSI] = "DSI2_PLL_FCLK", | ||
189 | [DSS_CLK_SRC_FCK] = "DSS1_ALWON_FCLK", | ||
190 | }; | ||
191 | |||
192 | static const char * const omap4_dss_clk_source_names[] = { | ||
193 | [DSS_CLK_SRC_DSI_PLL_HSDIV_DISPC] = "PLL1_CLK1", | ||
194 | [DSS_CLK_SRC_DSI_PLL_HSDIV_DSI] = "PLL1_CLK2", | ||
195 | [DSS_CLK_SRC_FCK] = "DSS_FCLK", | ||
196 | }; | ||
197 | |||
198 | static const struct dss_param_range omap2_dss_param_range[] = { | ||
199 | [FEAT_PARAM_DSS_FCK] = { 0, 173000000 }, | ||
200 | [FEAT_PARAM_DSIPLL_REGN] = { 0, 0 }, | ||
201 | [FEAT_PARAM_DSIPLL_REGM] = { 0, 0 }, | ||
202 | [FEAT_PARAM_DSIPLL_REGM_DISPC] = { 0, 0 }, | ||
203 | [FEAT_PARAM_DSIPLL_REGM_DSI] = { 0, 0 }, | ||
204 | [FEAT_PARAM_DSIPLL_FINT] = { 0, 0 }, | ||
205 | [FEAT_PARAM_DSIPLL_LPDIV] = { 0, 0 }, | ||
206 | }; | ||
207 | |||
208 | static const struct dss_param_range omap3_dss_param_range[] = { | ||
209 | [FEAT_PARAM_DSS_FCK] = { 0, 173000000 }, | ||
210 | [FEAT_PARAM_DSIPLL_REGN] = { 0, (1 << 7) - 1 }, | ||
211 | [FEAT_PARAM_DSIPLL_REGM] = { 0, (1 << 11) - 1 }, | ||
212 | [FEAT_PARAM_DSIPLL_REGM_DISPC] = { 0, (1 << 4) - 1 }, | ||
213 | [FEAT_PARAM_DSIPLL_REGM_DSI] = { 0, (1 << 4) - 1 }, | ||
214 | [FEAT_PARAM_DSIPLL_FINT] = { 750000, 2100000 }, | ||
215 | [FEAT_PARAM_DSIPLL_LPDIV] = { 1, (1 << 13) - 1}, | ||
216 | }; | ||
217 | |||
218 | static const struct dss_param_range omap4_dss_param_range[] = { | ||
219 | [FEAT_PARAM_DSS_FCK] = { 0, 186000000 }, | ||
220 | [FEAT_PARAM_DSIPLL_REGN] = { 0, (1 << 8) - 1 }, | ||
221 | [FEAT_PARAM_DSIPLL_REGM] = { 0, (1 << 12) - 1 }, | ||
222 | [FEAT_PARAM_DSIPLL_REGM_DISPC] = { 0, (1 << 5) - 1 }, | ||
223 | [FEAT_PARAM_DSIPLL_REGM_DSI] = { 0, (1 << 5) - 1 }, | ||
224 | [FEAT_PARAM_DSIPLL_FINT] = { 500000, 2500000 }, | ||
225 | [FEAT_PARAM_DSIPLL_LPDIV] = { 0, (1 << 13) - 1 }, | ||
226 | }; | ||
227 | |||
137 | /* OMAP2 DSS Features */ | 228 | /* OMAP2 DSS Features */ |
138 | static struct omap_dss_features omap2_dss_features = { | 229 | static struct omap_dss_features omap2_dss_features = { |
139 | .reg_fields = omap2_dss_reg_fields, | 230 | .reg_fields = omap2_dss_reg_fields, |
@@ -141,12 +232,15 @@ static struct omap_dss_features omap2_dss_features = { | |||
141 | 232 | ||
142 | .has_feature = | 233 | .has_feature = |
143 | FEAT_LCDENABLEPOL | FEAT_LCDENABLESIGNAL | | 234 | FEAT_LCDENABLEPOL | FEAT_LCDENABLESIGNAL | |
144 | FEAT_PCKFREEENABLE | FEAT_FUNCGATED, | 235 | FEAT_PCKFREEENABLE | FEAT_FUNCGATED | |
236 | FEAT_ROWREPEATENABLE | FEAT_RESIZECONF, | ||
145 | 237 | ||
146 | .num_mgrs = 2, | 238 | .num_mgrs = 2, |
147 | .num_ovls = 3, | 239 | .num_ovls = 3, |
148 | .supported_displays = omap2_dss_supported_displays, | 240 | .supported_displays = omap2_dss_supported_displays, |
149 | .supported_color_modes = omap2_dss_supported_color_modes, | 241 | .supported_color_modes = omap2_dss_supported_color_modes, |
242 | .clksrc_names = omap2_dss_clk_source_names, | ||
243 | .dss_params = omap2_dss_param_range, | ||
150 | }; | 244 | }; |
151 | 245 | ||
152 | /* OMAP3 DSS Features */ | 246 | /* OMAP3 DSS Features */ |
@@ -157,12 +251,15 @@ static struct omap_dss_features omap3430_dss_features = { | |||
157 | .has_feature = | 251 | .has_feature = |
158 | FEAT_GLOBAL_ALPHA | FEAT_LCDENABLEPOL | | 252 | FEAT_GLOBAL_ALPHA | FEAT_LCDENABLEPOL | |
159 | FEAT_LCDENABLESIGNAL | FEAT_PCKFREEENABLE | | 253 | FEAT_LCDENABLESIGNAL | FEAT_PCKFREEENABLE | |
160 | FEAT_FUNCGATED, | 254 | FEAT_FUNCGATED | FEAT_ROWREPEATENABLE | |
255 | FEAT_LINEBUFFERSPLIT | FEAT_RESIZECONF, | ||
161 | 256 | ||
162 | .num_mgrs = 2, | 257 | .num_mgrs = 2, |
163 | .num_ovls = 3, | 258 | .num_ovls = 3, |
164 | .supported_displays = omap3_dss_supported_displays, | 259 | .supported_displays = omap3430_dss_supported_displays, |
165 | .supported_color_modes = omap3_dss_supported_color_modes, | 260 | .supported_color_modes = omap3_dss_supported_color_modes, |
261 | .clksrc_names = omap3_dss_clk_source_names, | ||
262 | .dss_params = omap3_dss_param_range, | ||
166 | }; | 263 | }; |
167 | 264 | ||
168 | static struct omap_dss_features omap3630_dss_features = { | 265 | static struct omap_dss_features omap3630_dss_features = { |
@@ -172,27 +269,34 @@ static struct omap_dss_features omap3630_dss_features = { | |||
172 | .has_feature = | 269 | .has_feature = |
173 | FEAT_GLOBAL_ALPHA | FEAT_LCDENABLEPOL | | 270 | FEAT_GLOBAL_ALPHA | FEAT_LCDENABLEPOL | |
174 | FEAT_LCDENABLESIGNAL | FEAT_PCKFREEENABLE | | 271 | FEAT_LCDENABLESIGNAL | FEAT_PCKFREEENABLE | |
175 | FEAT_PRE_MULT_ALPHA | FEAT_FUNCGATED, | 272 | FEAT_PRE_MULT_ALPHA | FEAT_FUNCGATED | |
273 | FEAT_ROWREPEATENABLE | FEAT_LINEBUFFERSPLIT | | ||
274 | FEAT_RESIZECONF, | ||
176 | 275 | ||
177 | .num_mgrs = 2, | 276 | .num_mgrs = 2, |
178 | .num_ovls = 3, | 277 | .num_ovls = 3, |
179 | .supported_displays = omap3_dss_supported_displays, | 278 | .supported_displays = omap3630_dss_supported_displays, |
180 | .supported_color_modes = omap3_dss_supported_color_modes, | 279 | .supported_color_modes = omap3_dss_supported_color_modes, |
280 | .clksrc_names = omap3_dss_clk_source_names, | ||
281 | .dss_params = omap3_dss_param_range, | ||
181 | }; | 282 | }; |
182 | 283 | ||
183 | /* OMAP4 DSS Features */ | 284 | /* OMAP4 DSS Features */ |
184 | static struct omap_dss_features omap4_dss_features = { | 285 | static struct omap_dss_features omap4_dss_features = { |
185 | .reg_fields = omap3_dss_reg_fields, | 286 | .reg_fields = omap4_dss_reg_fields, |
186 | .num_reg_fields = ARRAY_SIZE(omap3_dss_reg_fields), | 287 | .num_reg_fields = ARRAY_SIZE(omap4_dss_reg_fields), |
187 | 288 | ||
188 | .has_feature = | 289 | .has_feature = |
189 | FEAT_GLOBAL_ALPHA | FEAT_PRE_MULT_ALPHA | | 290 | FEAT_GLOBAL_ALPHA | FEAT_PRE_MULT_ALPHA | |
190 | FEAT_MGR_LCD2, | 291 | FEAT_MGR_LCD2 | FEAT_GLOBAL_ALPHA_VID1 | |
292 | FEAT_CORE_CLK_DIV | FEAT_LCD_CLK_SRC, | ||
191 | 293 | ||
192 | .num_mgrs = 3, | 294 | .num_mgrs = 3, |
193 | .num_ovls = 3, | 295 | .num_ovls = 3, |
194 | .supported_displays = omap4_dss_supported_displays, | 296 | .supported_displays = omap4_dss_supported_displays, |
195 | .supported_color_modes = omap3_dss_supported_color_modes, | 297 | .supported_color_modes = omap3_dss_supported_color_modes, |
298 | .clksrc_names = omap4_dss_clk_source_names, | ||
299 | .dss_params = omap4_dss_param_range, | ||
196 | }; | 300 | }; |
197 | 301 | ||
198 | /* Functions returning values related to a DSS feature */ | 302 | /* Functions returning values related to a DSS feature */ |
@@ -206,6 +310,16 @@ int dss_feat_get_num_ovls(void) | |||
206 | return omap_current_dss_features->num_ovls; | 310 | return omap_current_dss_features->num_ovls; |
207 | } | 311 | } |
208 | 312 | ||
313 | unsigned long dss_feat_get_param_min(enum dss_range_param param) | ||
314 | { | ||
315 | return omap_current_dss_features->dss_params[param].min; | ||
316 | } | ||
317 | |||
318 | unsigned long dss_feat_get_param_max(enum dss_range_param param) | ||
319 | { | ||
320 | return omap_current_dss_features->dss_params[param].max; | ||
321 | } | ||
322 | |||
209 | enum omap_display_type dss_feat_get_supported_displays(enum omap_channel channel) | 323 | enum omap_display_type dss_feat_get_supported_displays(enum omap_channel channel) |
210 | { | 324 | { |
211 | return omap_current_dss_features->supported_displays[channel]; | 325 | return omap_current_dss_features->supported_displays[channel]; |
@@ -223,6 +337,11 @@ bool dss_feat_color_mode_supported(enum omap_plane plane, | |||
223 | color_mode; | 337 | color_mode; |
224 | } | 338 | } |
225 | 339 | ||
340 | const char *dss_feat_get_clk_source_name(enum dss_clk_source id) | ||
341 | { | ||
342 | return omap_current_dss_features->clksrc_names[id]; | ||
343 | } | ||
344 | |||
226 | /* DSS has_feature check */ | 345 | /* DSS has_feature check */ |
227 | bool dss_has_feature(enum dss_feat_id id) | 346 | bool dss_has_feature(enum dss_feat_id id) |
228 | { | 347 | { |
diff --git a/drivers/video/omap2/dss/dss_features.h b/drivers/video/omap2/dss/dss_features.h index b9c70be92588..12e9c4ef0dec 100644 --- a/drivers/video/omap2/dss/dss_features.h +++ b/drivers/video/omap2/dss/dss_features.h | |||
@@ -22,6 +22,7 @@ | |||
22 | 22 | ||
23 | #define MAX_DSS_MANAGERS 3 | 23 | #define MAX_DSS_MANAGERS 3 |
24 | #define MAX_DSS_OVERLAYS 3 | 24 | #define MAX_DSS_OVERLAYS 3 |
25 | #define MAX_DSS_LCD_MANAGERS 2 | ||
25 | 26 | ||
26 | /* DSS has feature id */ | 27 | /* DSS has feature id */ |
27 | enum dss_feat_id { | 28 | enum dss_feat_id { |
@@ -33,6 +34,12 @@ enum dss_feat_id { | |||
33 | FEAT_PCKFREEENABLE = 1 << 5, | 34 | FEAT_PCKFREEENABLE = 1 << 5, |
34 | FEAT_FUNCGATED = 1 << 6, | 35 | FEAT_FUNCGATED = 1 << 6, |
35 | FEAT_MGR_LCD2 = 1 << 7, | 36 | FEAT_MGR_LCD2 = 1 << 7, |
37 | FEAT_LINEBUFFERSPLIT = 1 << 8, | ||
38 | FEAT_ROWREPEATENABLE = 1 << 9, | ||
39 | FEAT_RESIZECONF = 1 << 10, | ||
40 | /* Independent core clk divider */ | ||
41 | FEAT_CORE_CLK_DIV = 1 << 11, | ||
42 | FEAT_LCD_CLK_SRC = 1 << 12, | ||
36 | }; | 43 | }; |
37 | 44 | ||
38 | /* DSS register field id */ | 45 | /* DSS register field id */ |
@@ -42,15 +49,35 @@ enum dss_feat_reg_field { | |||
42 | FEAT_REG_FIFOHIGHTHRESHOLD, | 49 | FEAT_REG_FIFOHIGHTHRESHOLD, |
43 | FEAT_REG_FIFOLOWTHRESHOLD, | 50 | FEAT_REG_FIFOLOWTHRESHOLD, |
44 | FEAT_REG_FIFOSIZE, | 51 | FEAT_REG_FIFOSIZE, |
52 | FEAT_REG_HORIZONTALACCU, | ||
53 | FEAT_REG_VERTICALACCU, | ||
54 | FEAT_REG_DISPC_CLK_SWITCH, | ||
55 | FEAT_REG_DSIPLL_REGN, | ||
56 | FEAT_REG_DSIPLL_REGM, | ||
57 | FEAT_REG_DSIPLL_REGM_DISPC, | ||
58 | FEAT_REG_DSIPLL_REGM_DSI, | ||
59 | }; | ||
60 | |||
61 | enum dss_range_param { | ||
62 | FEAT_PARAM_DSS_FCK, | ||
63 | FEAT_PARAM_DSIPLL_REGN, | ||
64 | FEAT_PARAM_DSIPLL_REGM, | ||
65 | FEAT_PARAM_DSIPLL_REGM_DISPC, | ||
66 | FEAT_PARAM_DSIPLL_REGM_DSI, | ||
67 | FEAT_PARAM_DSIPLL_FINT, | ||
68 | FEAT_PARAM_DSIPLL_LPDIV, | ||
45 | }; | 69 | }; |
46 | 70 | ||
47 | /* DSS Feature Functions */ | 71 | /* DSS Feature Functions */ |
48 | int dss_feat_get_num_mgrs(void); | 72 | int dss_feat_get_num_mgrs(void); |
49 | int dss_feat_get_num_ovls(void); | 73 | int dss_feat_get_num_ovls(void); |
74 | unsigned long dss_feat_get_param_min(enum dss_range_param param); | ||
75 | unsigned long dss_feat_get_param_max(enum dss_range_param param); | ||
50 | enum omap_display_type dss_feat_get_supported_displays(enum omap_channel channel); | 76 | enum omap_display_type dss_feat_get_supported_displays(enum omap_channel channel); |
51 | enum omap_color_mode dss_feat_get_supported_color_modes(enum omap_plane plane); | 77 | enum omap_color_mode dss_feat_get_supported_color_modes(enum omap_plane plane); |
52 | bool dss_feat_color_mode_supported(enum omap_plane plane, | 78 | bool dss_feat_color_mode_supported(enum omap_plane plane, |
53 | enum omap_color_mode color_mode); | 79 | enum omap_color_mode color_mode); |
80 | const char *dss_feat_get_clk_source_name(enum dss_clk_source id); | ||
54 | 81 | ||
55 | bool dss_has_feature(enum dss_feat_id id); | 82 | bool dss_has_feature(enum dss_feat_id id); |
56 | void dss_feat_get_reg_field(enum dss_feat_reg_field id, u8 *start, u8 *end); | 83 | void dss_feat_get_reg_field(enum dss_feat_reg_field id, u8 *start, u8 *end); |
diff --git a/drivers/video/omap2/dss/hdmi.c b/drivers/video/omap2/dss/hdmi.c new file mode 100644 index 000000000000..0d44f070ef36 --- /dev/null +++ b/drivers/video/omap2/dss/hdmi.c | |||
@@ -0,0 +1,1332 @@ | |||
1 | /* | ||
2 | * hdmi.c | ||
3 | * | ||
4 | * HDMI interface DSS driver setting for TI's OMAP4 family of processor. | ||
5 | * Copyright (C) 2010-2011 Texas Instruments Incorporated - http://www.ti.com/ | ||
6 | * Authors: Yong Zhi | ||
7 | * Mythri pk <mythripk@ti.com> | ||
8 | * | ||
9 | * This program is free software; you can redistribute it and/or modify it | ||
10 | * under the terms of the GNU General Public License version 2 as published by | ||
11 | * the Free Software Foundation. | ||
12 | * | ||
13 | * This program is distributed in the hope that it will be useful, but WITHOUT | ||
14 | * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or | ||
15 | * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for | ||
16 | * more details. | ||
17 | * | ||
18 | * You should have received a copy of the GNU General Public License along with | ||
19 | * this program. If not, see <http://www.gnu.org/licenses/>. | ||
20 | */ | ||
21 | |||
22 | #define DSS_SUBSYS_NAME "HDMI" | ||
23 | |||
24 | #include <linux/kernel.h> | ||
25 | #include <linux/module.h> | ||
26 | #include <linux/err.h> | ||
27 | #include <linux/io.h> | ||
28 | #include <linux/interrupt.h> | ||
29 | #include <linux/mutex.h> | ||
30 | #include <linux/delay.h> | ||
31 | #include <linux/string.h> | ||
32 | #include <plat/display.h> | ||
33 | |||
34 | #include "dss.h" | ||
35 | #include "hdmi.h" | ||
36 | |||
37 | static struct { | ||
38 | struct mutex lock; | ||
39 | struct omap_display_platform_data *pdata; | ||
40 | struct platform_device *pdev; | ||
41 | void __iomem *base_wp; /* HDMI wrapper */ | ||
42 | int code; | ||
43 | int mode; | ||
44 | u8 edid[HDMI_EDID_MAX_LENGTH]; | ||
45 | u8 edid_set; | ||
46 | bool custom_set; | ||
47 | struct hdmi_config cfg; | ||
48 | } hdmi; | ||
49 | |||
50 | /* | ||
51 | * Logic for the below structure : | ||
52 | * user enters the CEA or VESA timings by specifying the HDMI/DVI code. | ||
53 | * There is a correspondence between CEA/VESA timing and code, please | ||
54 | * refer to section 6.3 in HDMI 1.3 specification for timing code. | ||
55 | * | ||
56 | * In the below structure, cea_vesa_timings corresponds to all OMAP4 | ||
57 | * supported CEA and VESA timing values.code_cea corresponds to the CEA | ||
58 | * code, It is used to get the timing from cea_vesa_timing array.Similarly | ||
59 | * with code_vesa. Code_index is used for back mapping, that is once EDID | ||
60 | * is read from the TV, EDID is parsed to find the timing values and then | ||
61 | * map it to corresponding CEA or VESA index. | ||
62 | */ | ||
63 | |||
64 | static const struct hdmi_timings cea_vesa_timings[OMAP_HDMI_TIMINGS_NB] = { | ||
65 | { {640, 480, 25200, 96, 16, 48, 2, 10, 33} , 0 , 0}, | ||
66 | { {1280, 720, 74250, 40, 440, 220, 5, 5, 20}, 1, 1}, | ||
67 | { {1280, 720, 74250, 40, 110, 220, 5, 5, 20}, 1, 1}, | ||
68 | { {720, 480, 27027, 62, 16, 60, 6, 9, 30}, 0, 0}, | ||
69 | { {2880, 576, 108000, 256, 48, 272, 5, 5, 39}, 0, 0}, | ||
70 | { {1440, 240, 27027, 124, 38, 114, 3, 4, 15}, 0, 0}, | ||
71 | { {1440, 288, 27000, 126, 24, 138, 3, 2, 19}, 0, 0}, | ||
72 | { {1920, 540, 74250, 44, 528, 148, 5, 2, 15}, 1, 1}, | ||
73 | { {1920, 540, 74250, 44, 88, 148, 5, 2, 15}, 1, 1}, | ||
74 | { {1920, 1080, 148500, 44, 88, 148, 5, 4, 36}, 1, 1}, | ||
75 | { {720, 576, 27000, 64, 12, 68, 5, 5, 39}, 0, 0}, | ||
76 | { {1440, 576, 54000, 128, 24, 136, 5, 5, 39}, 0, 0}, | ||
77 | { {1920, 1080, 148500, 44, 528, 148, 5, 4, 36}, 1, 1}, | ||
78 | { {2880, 480, 108108, 248, 64, 240, 6, 9, 30}, 0, 0}, | ||
79 | { {1920, 1080, 74250, 44, 638, 148, 5, 4, 36}, 1, 1}, | ||
80 | /* VESA From Here */ | ||
81 | { {640, 480, 25175, 96, 16, 48, 2 , 11, 31}, 0, 0}, | ||
82 | { {800, 600, 40000, 128, 40, 88, 4 , 1, 23}, 1, 1}, | ||
83 | { {848, 480, 33750, 112, 16, 112, 8 , 6, 23}, 1, 1}, | ||
84 | { {1280, 768, 79500, 128, 64, 192, 7 , 3, 20}, 1, 0}, | ||
85 | { {1280, 800, 83500, 128, 72, 200, 6 , 3, 22}, 1, 0}, | ||
86 | { {1360, 768, 85500, 112, 64, 256, 6 , 3, 18}, 1, 1}, | ||
87 | { {1280, 960, 108000, 112, 96, 312, 3 , 1, 36}, 1, 1}, | ||
88 | { {1280, 1024, 108000, 112, 48, 248, 3 , 1, 38}, 1, 1}, | ||
89 | { {1024, 768, 65000, 136, 24, 160, 6, 3, 29}, 0, 0}, | ||
90 | { {1400, 1050, 121750, 144, 88, 232, 4, 3, 32}, 1, 0}, | ||
91 | { {1440, 900, 106500, 152, 80, 232, 6, 3, 25}, 1, 0}, | ||
92 | { {1680, 1050, 146250, 176 , 104, 280, 6, 3, 30}, 1, 0}, | ||
93 | { {1366, 768, 85500, 143, 70, 213, 3, 3, 24}, 1, 1}, | ||
94 | { {1920, 1080, 148500, 44, 148, 80, 5, 4, 36}, 1, 1}, | ||
95 | { {1280, 768, 68250, 32, 48, 80, 7, 3, 12}, 0, 1}, | ||
96 | { {1400, 1050, 101000, 32, 48, 80, 4, 3, 23}, 0, 1}, | ||
97 | { {1680, 1050, 119000, 32, 48, 80, 6, 3, 21}, 0, 1}, | ||
98 | { {1280, 800, 79500, 32, 48, 80, 6, 3, 14}, 0, 1}, | ||
99 | { {1280, 720, 74250, 40, 110, 220, 5, 5, 20}, 1, 1} | ||
100 | }; | ||
101 | |||
102 | /* | ||
103 | * This is a static mapping array which maps the timing values | ||
104 | * with corresponding CEA / VESA code | ||
105 | */ | ||
106 | static const int code_index[OMAP_HDMI_TIMINGS_NB] = { | ||
107 | 1, 19, 4, 2, 37, 6, 21, 20, 5, 16, 17, 29, 31, 35, 32, | ||
108 | /* <--15 CEA 17--> vesa*/ | ||
109 | 4, 9, 0xE, 0x17, 0x1C, 0x27, 0x20, 0x23, 0x10, 0x2A, | ||
110 | 0X2F, 0x3A, 0X51, 0X52, 0x16, 0x29, 0x39, 0x1B | ||
111 | }; | ||
112 | |||
113 | /* | ||
114 | * This is reverse static mapping which maps the CEA / VESA code | ||
115 | * to the corresponding timing values | ||
116 | */ | ||
117 | static const int code_cea[39] = { | ||
118 | -1, 0, 3, 3, 2, 8, 5, 5, -1, -1, | ||
119 | -1, -1, -1, -1, -1, -1, 9, 10, 10, 1, | ||
120 | 7, 6, 6, -1, -1, -1, -1, -1, -1, 11, | ||
121 | 11, 12, 14, -1, -1, 13, 13, 4, 4 | ||
122 | }; | ||
123 | |||
124 | static const int code_vesa[85] = { | ||
125 | -1, -1, -1, -1, 15, -1, -1, -1, -1, 16, | ||
126 | -1, -1, -1, -1, 17, -1, 23, -1, -1, -1, | ||
127 | -1, -1, 29, 18, -1, -1, -1, 32, 19, -1, | ||
128 | -1, -1, 21, -1, -1, 22, -1, -1, -1, 20, | ||
129 | -1, 30, 24, -1, -1, -1, -1, 25, -1, -1, | ||
130 | -1, -1, -1, -1, -1, -1, -1, 31, 26, -1, | ||
131 | -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, | ||
132 | -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, | ||
133 | -1, 27, 28, -1, 33}; | ||
134 | |||
135 | static const u8 edid_header[8] = {0x0, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x0}; | ||
136 | |||
137 | static inline void hdmi_write_reg(const struct hdmi_reg idx, u32 val) | ||
138 | { | ||
139 | __raw_writel(val, hdmi.base_wp + idx.idx); | ||
140 | } | ||
141 | |||
142 | static inline u32 hdmi_read_reg(const struct hdmi_reg idx) | ||
143 | { | ||
144 | return __raw_readl(hdmi.base_wp + idx.idx); | ||
145 | } | ||
146 | |||
147 | static inline int hdmi_wait_for_bit_change(const struct hdmi_reg idx, | ||
148 | int b2, int b1, u32 val) | ||
149 | { | ||
150 | u32 t = 0; | ||
151 | while (val != REG_GET(idx, b2, b1)) { | ||
152 | udelay(1); | ||
153 | if (t++ > 10000) | ||
154 | return !val; | ||
155 | } | ||
156 | return val; | ||
157 | } | ||
158 | |||
159 | int hdmi_init_display(struct omap_dss_device *dssdev) | ||
160 | { | ||
161 | DSSDBG("init_display\n"); | ||
162 | |||
163 | return 0; | ||
164 | } | ||
165 | |||
166 | static int hdmi_pll_init(enum hdmi_clk_refsel refsel, int dcofreq, | ||
167 | struct hdmi_pll_info *fmt, u16 sd) | ||
168 | { | ||
169 | u32 r; | ||
170 | |||
171 | /* PLL start always use manual mode */ | ||
172 | REG_FLD_MOD(PLLCTRL_PLL_CONTROL, 0x0, 0, 0); | ||
173 | |||
174 | r = hdmi_read_reg(PLLCTRL_CFG1); | ||
175 | r = FLD_MOD(r, fmt->regm, 20, 9); /* CFG1_PLL_REGM */ | ||
176 | r = FLD_MOD(r, fmt->regn, 8, 1); /* CFG1_PLL_REGN */ | ||
177 | |||
178 | hdmi_write_reg(PLLCTRL_CFG1, r); | ||
179 | |||
180 | r = hdmi_read_reg(PLLCTRL_CFG2); | ||
181 | |||
182 | r = FLD_MOD(r, 0x0, 12, 12); /* PLL_HIGHFREQ divide by 2 */ | ||
183 | r = FLD_MOD(r, 0x1, 13, 13); /* PLL_REFEN */ | ||
184 | r = FLD_MOD(r, 0x0, 14, 14); /* PHY_CLKINEN de-assert during locking */ | ||
185 | |||
186 | if (dcofreq) { | ||
187 | /* divider programming for frequency beyond 1000Mhz */ | ||
188 | REG_FLD_MOD(PLLCTRL_CFG3, sd, 17, 10); | ||
189 | r = FLD_MOD(r, 0x4, 3, 1); /* 1000MHz and 2000MHz */ | ||
190 | } else { | ||
191 | r = FLD_MOD(r, 0x2, 3, 1); /* 500MHz and 1000MHz */ | ||
192 | } | ||
193 | |||
194 | hdmi_write_reg(PLLCTRL_CFG2, r); | ||
195 | |||
196 | r = hdmi_read_reg(PLLCTRL_CFG4); | ||
197 | r = FLD_MOD(r, fmt->regm2, 24, 18); | ||
198 | r = FLD_MOD(r, fmt->regmf, 17, 0); | ||
199 | |||
200 | hdmi_write_reg(PLLCTRL_CFG4, r); | ||
201 | |||
202 | /* go now */ | ||
203 | REG_FLD_MOD(PLLCTRL_PLL_GO, 0x1, 0, 0); | ||
204 | |||
205 | /* wait for bit change */ | ||
206 | if (hdmi_wait_for_bit_change(PLLCTRL_PLL_GO, 0, 0, 1) != 1) { | ||
207 | DSSERR("PLL GO bit not set\n"); | ||
208 | return -ETIMEDOUT; | ||
209 | } | ||
210 | |||
211 | /* Wait till the lock bit is set in PLL status */ | ||
212 | if (hdmi_wait_for_bit_change(PLLCTRL_PLL_STATUS, 1, 1, 1) != 1) { | ||
213 | DSSWARN("cannot lock PLL\n"); | ||
214 | DSSWARN("CFG1 0x%x\n", | ||
215 | hdmi_read_reg(PLLCTRL_CFG1)); | ||
216 | DSSWARN("CFG2 0x%x\n", | ||
217 | hdmi_read_reg(PLLCTRL_CFG2)); | ||
218 | DSSWARN("CFG4 0x%x\n", | ||
219 | hdmi_read_reg(PLLCTRL_CFG4)); | ||
220 | return -ETIMEDOUT; | ||
221 | } | ||
222 | |||
223 | DSSDBG("PLL locked!\n"); | ||
224 | |||
225 | return 0; | ||
226 | } | ||
227 | |||
228 | /* PHY_PWR_CMD */ | ||
229 | static int hdmi_set_phy_pwr(enum hdmi_phy_pwr val) | ||
230 | { | ||
231 | /* Command for power control of HDMI PHY */ | ||
232 | REG_FLD_MOD(HDMI_WP_PWR_CTRL, val, 7, 6); | ||
233 | |||
234 | /* Status of the power control of HDMI PHY */ | ||
235 | if (hdmi_wait_for_bit_change(HDMI_WP_PWR_CTRL, 5, 4, val) != val) { | ||
236 | DSSERR("Failed to set PHY power mode to %d\n", val); | ||
237 | return -ETIMEDOUT; | ||
238 | } | ||
239 | |||
240 | return 0; | ||
241 | } | ||
242 | |||
243 | /* PLL_PWR_CMD */ | ||
244 | static int hdmi_set_pll_pwr(enum hdmi_pll_pwr val) | ||
245 | { | ||
246 | /* Command for power control of HDMI PLL */ | ||
247 | REG_FLD_MOD(HDMI_WP_PWR_CTRL, val, 3, 2); | ||
248 | |||
249 | /* wait till PHY_PWR_STATUS is set */ | ||
250 | if (hdmi_wait_for_bit_change(HDMI_WP_PWR_CTRL, 1, 0, val) != val) { | ||
251 | DSSERR("Failed to set PHY_PWR_STATUS\n"); | ||
252 | return -ETIMEDOUT; | ||
253 | } | ||
254 | |||
255 | return 0; | ||
256 | } | ||
257 | |||
258 | static int hdmi_pll_reset(void) | ||
259 | { | ||
260 | /* SYSRESET controlled by power FSM */ | ||
261 | REG_FLD_MOD(PLLCTRL_PLL_CONTROL, 0x0, 3, 3); | ||
262 | |||
263 | /* READ 0x0 reset is in progress */ | ||
264 | if (hdmi_wait_for_bit_change(PLLCTRL_PLL_STATUS, 0, 0, 1) != 1) { | ||
265 | DSSERR("Failed to sysreset PLL\n"); | ||
266 | return -ETIMEDOUT; | ||
267 | } | ||
268 | |||
269 | return 0; | ||
270 | } | ||
271 | |||
272 | static int hdmi_phy_init(void) | ||
273 | { | ||
274 | u16 r = 0; | ||
275 | |||
276 | r = hdmi_set_phy_pwr(HDMI_PHYPWRCMD_LDOON); | ||
277 | if (r) | ||
278 | return r; | ||
279 | |||
280 | r = hdmi_set_phy_pwr(HDMI_PHYPWRCMD_TXON); | ||
281 | if (r) | ||
282 | return r; | ||
283 | |||
284 | /* | ||
285 | * Read address 0 in order to get the SCP reset done completed | ||
286 | * Dummy access performed to make sure reset is done | ||
287 | */ | ||
288 | hdmi_read_reg(HDMI_TXPHY_TX_CTRL); | ||
289 | |||
290 | /* | ||
291 | * Write to phy address 0 to configure the clock | ||
292 | * use HFBITCLK write HDMI_TXPHY_TX_CONTROL_FREQOUT field | ||
293 | */ | ||
294 | REG_FLD_MOD(HDMI_TXPHY_TX_CTRL, 0x1, 31, 30); | ||
295 | |||
296 | /* Write to phy address 1 to start HDMI line (TXVALID and TMDSCLKEN) */ | ||
297 | hdmi_write_reg(HDMI_TXPHY_DIGITAL_CTRL, 0xF0000000); | ||
298 | |||
299 | /* Setup max LDO voltage */ | ||
300 | REG_FLD_MOD(HDMI_TXPHY_POWER_CTRL, 0xB, 3, 0); | ||
301 | |||
302 | /* Write to phy address 3 to change the polarity control */ | ||
303 | REG_FLD_MOD(HDMI_TXPHY_PAD_CFG_CTRL, 0x1, 27, 27); | ||
304 | |||
305 | return 0; | ||
306 | } | ||
307 | |||
308 | static int hdmi_wait_softreset(void) | ||
309 | { | ||
310 | /* reset W1 */ | ||
311 | REG_FLD_MOD(HDMI_WP_SYSCONFIG, 0x1, 0, 0); | ||
312 | |||
313 | /* wait till SOFTRESET == 0 */ | ||
314 | if (hdmi_wait_for_bit_change(HDMI_WP_SYSCONFIG, 0, 0, 0) != 0) { | ||
315 | DSSERR("sysconfig reset failed\n"); | ||
316 | return -ETIMEDOUT; | ||
317 | } | ||
318 | |||
319 | return 0; | ||
320 | } | ||
321 | |||
322 | static int hdmi_pll_program(struct hdmi_pll_info *fmt) | ||
323 | { | ||
324 | u16 r = 0; | ||
325 | enum hdmi_clk_refsel refsel; | ||
326 | |||
327 | /* wait for wrapper reset */ | ||
328 | r = hdmi_wait_softreset(); | ||
329 | if (r) | ||
330 | return r; | ||
331 | |||
332 | r = hdmi_set_pll_pwr(HDMI_PLLPWRCMD_ALLOFF); | ||
333 | if (r) | ||
334 | return r; | ||
335 | |||
336 | r = hdmi_set_pll_pwr(HDMI_PLLPWRCMD_BOTHON_ALLCLKS); | ||
337 | if (r) | ||
338 | return r; | ||
339 | |||
340 | r = hdmi_pll_reset(); | ||
341 | if (r) | ||
342 | return r; | ||
343 | |||
344 | refsel = HDMI_REFSEL_SYSCLK; | ||
345 | |||
346 | r = hdmi_pll_init(refsel, fmt->dcofreq, fmt, fmt->regsd); | ||
347 | if (r) | ||
348 | return r; | ||
349 | |||
350 | return 0; | ||
351 | } | ||
352 | |||
353 | static void hdmi_phy_off(void) | ||
354 | { | ||
355 | hdmi_set_phy_pwr(HDMI_PHYPWRCMD_OFF); | ||
356 | } | ||
357 | |||
358 | static int hdmi_core_ddc_edid(u8 *pedid, int ext) | ||
359 | { | ||
360 | u32 i, j; | ||
361 | char checksum = 0; | ||
362 | u32 offset = 0; | ||
363 | |||
364 | /* Turn on CLK for DDC */ | ||
365 | REG_FLD_MOD(HDMI_CORE_AV_DPD, 0x7, 2, 0); | ||
366 | |||
367 | /* | ||
368 | * SW HACK : Without the Delay DDC(i2c bus) reads 0 values / | ||
369 | * right shifted values( The behavior is not consistent and seen only | ||
370 | * with some TV's) | ||
371 | */ | ||
372 | usleep_range(800, 1000); | ||
373 | |||
374 | if (!ext) { | ||
375 | /* Clk SCL Devices */ | ||
376 | REG_FLD_MOD(HDMI_CORE_DDC_CMD, 0xA, 3, 0); | ||
377 | |||
378 | /* HDMI_CORE_DDC_STATUS_IN_PROG */ | ||
379 | if (hdmi_wait_for_bit_change(HDMI_CORE_DDC_STATUS, | ||
380 | 4, 4, 0) != 0) { | ||
381 | DSSERR("Failed to program DDC\n"); | ||
382 | return -ETIMEDOUT; | ||
383 | } | ||
384 | |||
385 | /* Clear FIFO */ | ||
386 | REG_FLD_MOD(HDMI_CORE_DDC_CMD, 0x9, 3, 0); | ||
387 | |||
388 | /* HDMI_CORE_DDC_STATUS_IN_PROG */ | ||
389 | if (hdmi_wait_for_bit_change(HDMI_CORE_DDC_STATUS, | ||
390 | 4, 4, 0) != 0) { | ||
391 | DSSERR("Failed to program DDC\n"); | ||
392 | return -ETIMEDOUT; | ||
393 | } | ||
394 | |||
395 | } else { | ||
396 | if (ext % 2 != 0) | ||
397 | offset = 0x80; | ||
398 | } | ||
399 | |||
400 | /* Load Segment Address Register */ | ||
401 | REG_FLD_MOD(HDMI_CORE_DDC_SEGM, ext/2, 7, 0); | ||
402 | |||
403 | /* Load Slave Address Register */ | ||
404 | REG_FLD_MOD(HDMI_CORE_DDC_ADDR, 0xA0 >> 1, 7, 1); | ||
405 | |||
406 | /* Load Offset Address Register */ | ||
407 | REG_FLD_MOD(HDMI_CORE_DDC_OFFSET, offset, 7, 0); | ||
408 | |||
409 | /* Load Byte Count */ | ||
410 | REG_FLD_MOD(HDMI_CORE_DDC_COUNT1, 0x80, 7, 0); | ||
411 | REG_FLD_MOD(HDMI_CORE_DDC_COUNT2, 0x0, 1, 0); | ||
412 | |||
413 | /* Set DDC_CMD */ | ||
414 | if (ext) | ||
415 | REG_FLD_MOD(HDMI_CORE_DDC_CMD, 0x4, 3, 0); | ||
416 | else | ||
417 | REG_FLD_MOD(HDMI_CORE_DDC_CMD, 0x2, 3, 0); | ||
418 | |||
419 | /* HDMI_CORE_DDC_STATUS_BUS_LOW */ | ||
420 | if (REG_GET(HDMI_CORE_DDC_STATUS, 6, 6) == 1) { | ||
421 | DSSWARN("I2C Bus Low?\n"); | ||
422 | return -EIO; | ||
423 | } | ||
424 | /* HDMI_CORE_DDC_STATUS_NO_ACK */ | ||
425 | if (REG_GET(HDMI_CORE_DDC_STATUS, 5, 5) == 1) { | ||
426 | DSSWARN("I2C No Ack\n"); | ||
427 | return -EIO; | ||
428 | } | ||
429 | |||
430 | i = ext * 128; | ||
431 | j = 0; | ||
432 | while (((REG_GET(HDMI_CORE_DDC_STATUS, 4, 4) == 1) || | ||
433 | (REG_GET(HDMI_CORE_DDC_STATUS, 2, 2) == 0)) && | ||
434 | j < 128) { | ||
435 | |||
436 | if (REG_GET(HDMI_CORE_DDC_STATUS, 2, 2) == 0) { | ||
437 | /* FIFO not empty */ | ||
438 | pedid[i++] = REG_GET(HDMI_CORE_DDC_DATA, 7, 0); | ||
439 | j++; | ||
440 | } | ||
441 | } | ||
442 | |||
443 | for (j = 0; j < 128; j++) | ||
444 | checksum += pedid[j]; | ||
445 | |||
446 | if (checksum != 0) { | ||
447 | DSSERR("E-EDID checksum failed!!\n"); | ||
448 | return -EIO; | ||
449 | } | ||
450 | |||
451 | return 0; | ||
452 | } | ||
453 | |||
454 | static int read_edid(u8 *pedid, u16 max_length) | ||
455 | { | ||
456 | int r = 0, n = 0, i = 0; | ||
457 | int max_ext_blocks = (max_length / 128) - 1; | ||
458 | |||
459 | r = hdmi_core_ddc_edid(pedid, 0); | ||
460 | if (r) { | ||
461 | return r; | ||
462 | } else { | ||
463 | n = pedid[0x7e]; | ||
464 | |||
465 | /* | ||
466 | * README: need to comply with max_length set by the caller. | ||
467 | * Better implementation should be to allocate necessary | ||
468 | * memory to store EDID according to nb_block field found | ||
469 | * in first block | ||
470 | */ | ||
471 | if (n > max_ext_blocks) | ||
472 | n = max_ext_blocks; | ||
473 | |||
474 | for (i = 1; i <= n; i++) { | ||
475 | r = hdmi_core_ddc_edid(pedid, i); | ||
476 | if (r) | ||
477 | return r; | ||
478 | } | ||
479 | } | ||
480 | return 0; | ||
481 | } | ||
482 | |||
483 | static int get_timings_index(void) | ||
484 | { | ||
485 | int code; | ||
486 | |||
487 | if (hdmi.mode == 0) | ||
488 | code = code_vesa[hdmi.code]; | ||
489 | else | ||
490 | code = code_cea[hdmi.code]; | ||
491 | |||
492 | if (code == -1) { | ||
493 | /* HDMI code 4 corresponds to 640 * 480 VGA */ | ||
494 | hdmi.code = 4; | ||
495 | /* DVI mode 1 corresponds to HDMI 0 to DVI */ | ||
496 | hdmi.mode = HDMI_DVI; | ||
497 | |||
498 | code = code_vesa[hdmi.code]; | ||
499 | } | ||
500 | return code; | ||
501 | } | ||
502 | |||
503 | static struct hdmi_cm hdmi_get_code(struct omap_video_timings *timing) | ||
504 | { | ||
505 | int i = 0, code = -1, temp_vsync = 0, temp_hsync = 0; | ||
506 | int timing_vsync = 0, timing_hsync = 0; | ||
507 | struct omap_video_timings temp; | ||
508 | struct hdmi_cm cm = {-1}; | ||
509 | DSSDBG("hdmi_get_code\n"); | ||
510 | |||
511 | for (i = 0; i < OMAP_HDMI_TIMINGS_NB; i++) { | ||
512 | temp = cea_vesa_timings[i].timings; | ||
513 | if ((temp.pixel_clock == timing->pixel_clock) && | ||
514 | (temp.x_res == timing->x_res) && | ||
515 | (temp.y_res == timing->y_res)) { | ||
516 | |||
517 | temp_hsync = temp.hfp + temp.hsw + temp.hbp; | ||
518 | timing_hsync = timing->hfp + timing->hsw + timing->hbp; | ||
519 | temp_vsync = temp.vfp + temp.vsw + temp.vbp; | ||
520 | timing_vsync = timing->vfp + timing->vsw + timing->vbp; | ||
521 | |||
522 | DSSDBG("temp_hsync = %d , temp_vsync = %d" | ||
523 | "timing_hsync = %d, timing_vsync = %d\n", | ||
524 | temp_hsync, temp_hsync, | ||
525 | timing_hsync, timing_vsync); | ||
526 | |||
527 | if ((temp_hsync == timing_hsync) && | ||
528 | (temp_vsync == timing_vsync)) { | ||
529 | code = i; | ||
530 | cm.code = code_index[i]; | ||
531 | if (code < 14) | ||
532 | cm.mode = HDMI_HDMI; | ||
533 | else | ||
534 | cm.mode = HDMI_DVI; | ||
535 | DSSDBG("Hdmi_code = %d mode = %d\n", | ||
536 | cm.code, cm.mode); | ||
537 | break; | ||
538 | } | ||
539 | } | ||
540 | } | ||
541 | |||
542 | return cm; | ||
543 | } | ||
544 | |||
545 | static void get_horz_vert_timing_info(int current_descriptor_addrs, u8 *edid , | ||
546 | struct omap_video_timings *timings) | ||
547 | { | ||
548 | /* X and Y resolution */ | ||
549 | timings->x_res = (((edid[current_descriptor_addrs + 4] & 0xF0) << 4) | | ||
550 | edid[current_descriptor_addrs + 2]); | ||
551 | timings->y_res = (((edid[current_descriptor_addrs + 7] & 0xF0) << 4) | | ||
552 | edid[current_descriptor_addrs + 5]); | ||
553 | |||
554 | timings->pixel_clock = ((edid[current_descriptor_addrs + 1] << 8) | | ||
555 | edid[current_descriptor_addrs]); | ||
556 | |||
557 | timings->pixel_clock = 10 * timings->pixel_clock; | ||
558 | |||
559 | /* HORIZONTAL FRONT PORCH */ | ||
560 | timings->hfp = edid[current_descriptor_addrs + 8] | | ||
561 | ((edid[current_descriptor_addrs + 11] & 0xc0) << 2); | ||
562 | /* HORIZONTAL SYNC WIDTH */ | ||
563 | timings->hsw = edid[current_descriptor_addrs + 9] | | ||
564 | ((edid[current_descriptor_addrs + 11] & 0x30) << 4); | ||
565 | /* HORIZONTAL BACK PORCH */ | ||
566 | timings->hbp = (((edid[current_descriptor_addrs + 4] & 0x0F) << 8) | | ||
567 | edid[current_descriptor_addrs + 3]) - | ||
568 | (timings->hfp + timings->hsw); | ||
569 | /* VERTICAL FRONT PORCH */ | ||
570 | timings->vfp = ((edid[current_descriptor_addrs + 10] & 0xF0) >> 4) | | ||
571 | ((edid[current_descriptor_addrs + 11] & 0x0f) << 2); | ||
572 | /* VERTICAL SYNC WIDTH */ | ||
573 | timings->vsw = (edid[current_descriptor_addrs + 10] & 0x0F) | | ||
574 | ((edid[current_descriptor_addrs + 11] & 0x03) << 4); | ||
575 | /* VERTICAL BACK PORCH */ | ||
576 | timings->vbp = (((edid[current_descriptor_addrs + 7] & 0x0F) << 8) | | ||
577 | edid[current_descriptor_addrs + 6]) - | ||
578 | (timings->vfp + timings->vsw); | ||
579 | |||
580 | } | ||
581 | |||
582 | /* Description : This function gets the resolution information from EDID */ | ||
583 | static void get_edid_timing_data(u8 *edid) | ||
584 | { | ||
585 | u8 count; | ||
586 | u16 current_descriptor_addrs; | ||
587 | struct hdmi_cm cm; | ||
588 | struct omap_video_timings edid_timings; | ||
589 | |||
590 | /* seach block 0, there are 4 DTDs arranged in priority order */ | ||
591 | for (count = 0; count < EDID_SIZE_BLOCK0_TIMING_DESCRIPTOR; count++) { | ||
592 | current_descriptor_addrs = | ||
593 | EDID_DESCRIPTOR_BLOCK0_ADDRESS + | ||
594 | count * EDID_TIMING_DESCRIPTOR_SIZE; | ||
595 | get_horz_vert_timing_info(current_descriptor_addrs, | ||
596 | edid, &edid_timings); | ||
597 | cm = hdmi_get_code(&edid_timings); | ||
598 | DSSDBG("Block0[%d] value matches code = %d , mode = %d\n", | ||
599 | count, cm.code, cm.mode); | ||
600 | if (cm.code == -1) { | ||
601 | continue; | ||
602 | } else { | ||
603 | hdmi.code = cm.code; | ||
604 | hdmi.mode = cm.mode; | ||
605 | DSSDBG("code = %d , mode = %d\n", | ||
606 | hdmi.code, hdmi.mode); | ||
607 | return; | ||
608 | } | ||
609 | } | ||
610 | if (edid[0x7e] != 0x00) { | ||
611 | for (count = 0; count < EDID_SIZE_BLOCK1_TIMING_DESCRIPTOR; | ||
612 | count++) { | ||
613 | current_descriptor_addrs = | ||
614 | EDID_DESCRIPTOR_BLOCK1_ADDRESS + | ||
615 | count * EDID_TIMING_DESCRIPTOR_SIZE; | ||
616 | get_horz_vert_timing_info(current_descriptor_addrs, | ||
617 | edid, &edid_timings); | ||
618 | cm = hdmi_get_code(&edid_timings); | ||
619 | DSSDBG("Block1[%d] value matches code = %d, mode = %d", | ||
620 | count, cm.code, cm.mode); | ||
621 | if (cm.code == -1) { | ||
622 | continue; | ||
623 | } else { | ||
624 | hdmi.code = cm.code; | ||
625 | hdmi.mode = cm.mode; | ||
626 | DSSDBG("code = %d , mode = %d\n", | ||
627 | hdmi.code, hdmi.mode); | ||
628 | return; | ||
629 | } | ||
630 | } | ||
631 | } | ||
632 | |||
633 | DSSINFO("no valid timing found , falling back to VGA\n"); | ||
634 | hdmi.code = 4; /* setting default value of 640 480 VGA */ | ||
635 | hdmi.mode = HDMI_DVI; | ||
636 | } | ||
637 | |||
638 | static void hdmi_read_edid(struct omap_video_timings *dp) | ||
639 | { | ||
640 | int ret = 0, code; | ||
641 | |||
642 | memset(hdmi.edid, 0, HDMI_EDID_MAX_LENGTH); | ||
643 | |||
644 | if (!hdmi.edid_set) | ||
645 | ret = read_edid(hdmi.edid, HDMI_EDID_MAX_LENGTH); | ||
646 | |||
647 | if (!ret) { | ||
648 | if (!memcmp(hdmi.edid, edid_header, sizeof(edid_header))) { | ||
649 | /* search for timings of default resolution */ | ||
650 | get_edid_timing_data(hdmi.edid); | ||
651 | hdmi.edid_set = true; | ||
652 | } | ||
653 | } else { | ||
654 | DSSWARN("failed to read E-EDID\n"); | ||
655 | } | ||
656 | |||
657 | if (!hdmi.edid_set) { | ||
658 | DSSINFO("fallback to VGA\n"); | ||
659 | hdmi.code = 4; /* setting default value of 640 480 VGA */ | ||
660 | hdmi.mode = HDMI_DVI; | ||
661 | } | ||
662 | |||
663 | code = get_timings_index(); | ||
664 | |||
665 | *dp = cea_vesa_timings[code].timings; | ||
666 | } | ||
667 | |||
668 | static void hdmi_core_init(struct hdmi_core_video_config *video_cfg, | ||
669 | struct hdmi_core_infoframe_avi *avi_cfg, | ||
670 | struct hdmi_core_packet_enable_repeat *repeat_cfg) | ||
671 | { | ||
672 | DSSDBG("Enter hdmi_core_init\n"); | ||
673 | |||
674 | /* video core */ | ||
675 | video_cfg->ip_bus_width = HDMI_INPUT_8BIT; | ||
676 | video_cfg->op_dither_truc = HDMI_OUTPUTTRUNCATION_8BIT; | ||
677 | video_cfg->deep_color_pkt = HDMI_DEEPCOLORPACKECTDISABLE; | ||
678 | video_cfg->pkt_mode = HDMI_PACKETMODERESERVEDVALUE; | ||
679 | video_cfg->hdmi_dvi = HDMI_DVI; | ||
680 | video_cfg->tclk_sel_clkmult = HDMI_FPLL10IDCK; | ||
681 | |||
682 | /* info frame */ | ||
683 | avi_cfg->db1_format = 0; | ||
684 | avi_cfg->db1_active_info = 0; | ||
685 | avi_cfg->db1_bar_info_dv = 0; | ||
686 | avi_cfg->db1_scan_info = 0; | ||
687 | avi_cfg->db2_colorimetry = 0; | ||
688 | avi_cfg->db2_aspect_ratio = 0; | ||
689 | avi_cfg->db2_active_fmt_ar = 0; | ||
690 | avi_cfg->db3_itc = 0; | ||
691 | avi_cfg->db3_ec = 0; | ||
692 | avi_cfg->db3_q_range = 0; | ||
693 | avi_cfg->db3_nup_scaling = 0; | ||
694 | avi_cfg->db4_videocode = 0; | ||
695 | avi_cfg->db5_pixel_repeat = 0; | ||
696 | avi_cfg->db6_7_line_eoftop = 0 ; | ||
697 | avi_cfg->db8_9_line_sofbottom = 0; | ||
698 | avi_cfg->db10_11_pixel_eofleft = 0; | ||
699 | avi_cfg->db12_13_pixel_sofright = 0; | ||
700 | |||
701 | /* packet enable and repeat */ | ||
702 | repeat_cfg->audio_pkt = 0; | ||
703 | repeat_cfg->audio_pkt_repeat = 0; | ||
704 | repeat_cfg->avi_infoframe = 0; | ||
705 | repeat_cfg->avi_infoframe_repeat = 0; | ||
706 | repeat_cfg->gen_cntrl_pkt = 0; | ||
707 | repeat_cfg->gen_cntrl_pkt_repeat = 0; | ||
708 | repeat_cfg->generic_pkt = 0; | ||
709 | repeat_cfg->generic_pkt_repeat = 0; | ||
710 | } | ||
711 | |||
712 | static void hdmi_core_powerdown_disable(void) | ||
713 | { | ||
714 | DSSDBG("Enter hdmi_core_powerdown_disable\n"); | ||
715 | REG_FLD_MOD(HDMI_CORE_CTRL1, 0x0, 0, 0); | ||
716 | } | ||
717 | |||
718 | static void hdmi_core_swreset_release(void) | ||
719 | { | ||
720 | DSSDBG("Enter hdmi_core_swreset_release\n"); | ||
721 | REG_FLD_MOD(HDMI_CORE_SYS_SRST, 0x0, 0, 0); | ||
722 | } | ||
723 | |||
724 | static void hdmi_core_swreset_assert(void) | ||
725 | { | ||
726 | DSSDBG("Enter hdmi_core_swreset_assert\n"); | ||
727 | REG_FLD_MOD(HDMI_CORE_SYS_SRST, 0x1, 0, 0); | ||
728 | } | ||
729 | |||
730 | /* DSS_HDMI_CORE_VIDEO_CONFIG */ | ||
731 | static void hdmi_core_video_config(struct hdmi_core_video_config *cfg) | ||
732 | { | ||
733 | u32 r = 0; | ||
734 | |||
735 | /* sys_ctrl1 default configuration not tunable */ | ||
736 | r = hdmi_read_reg(HDMI_CORE_CTRL1); | ||
737 | r = FLD_MOD(r, HDMI_CORE_CTRL1_VEN_FOLLOWVSYNC, 5, 5); | ||
738 | r = FLD_MOD(r, HDMI_CORE_CTRL1_HEN_FOLLOWHSYNC, 4, 4); | ||
739 | r = FLD_MOD(r, HDMI_CORE_CTRL1_BSEL_24BITBUS, 2, 2); | ||
740 | r = FLD_MOD(r, HDMI_CORE_CTRL1_EDGE_RISINGEDGE, 1, 1); | ||
741 | hdmi_write_reg(HDMI_CORE_CTRL1, r); | ||
742 | |||
743 | REG_FLD_MOD(HDMI_CORE_SYS_VID_ACEN, cfg->ip_bus_width, 7, 6); | ||
744 | |||
745 | /* Vid_Mode */ | ||
746 | r = hdmi_read_reg(HDMI_CORE_SYS_VID_MODE); | ||
747 | |||
748 | /* dither truncation configuration */ | ||
749 | if (cfg->op_dither_truc > HDMI_OUTPUTTRUNCATION_12BIT) { | ||
750 | r = FLD_MOD(r, cfg->op_dither_truc - 3, 7, 6); | ||
751 | r = FLD_MOD(r, 1, 5, 5); | ||
752 | } else { | ||
753 | r = FLD_MOD(r, cfg->op_dither_truc, 7, 6); | ||
754 | r = FLD_MOD(r, 0, 5, 5); | ||
755 | } | ||
756 | hdmi_write_reg(HDMI_CORE_SYS_VID_MODE, r); | ||
757 | |||
758 | /* HDMI_Ctrl */ | ||
759 | r = hdmi_read_reg(HDMI_CORE_AV_HDMI_CTRL); | ||
760 | r = FLD_MOD(r, cfg->deep_color_pkt, 6, 6); | ||
761 | r = FLD_MOD(r, cfg->pkt_mode, 5, 3); | ||
762 | r = FLD_MOD(r, cfg->hdmi_dvi, 0, 0); | ||
763 | hdmi_write_reg(HDMI_CORE_AV_HDMI_CTRL, r); | ||
764 | |||
765 | /* TMDS_CTRL */ | ||
766 | REG_FLD_MOD(HDMI_CORE_SYS_TMDS_CTRL, | ||
767 | cfg->tclk_sel_clkmult, 6, 5); | ||
768 | } | ||
769 | |||
770 | static void hdmi_core_aux_infoframe_avi_config( | ||
771 | struct hdmi_core_infoframe_avi info_avi) | ||
772 | { | ||
773 | u32 val; | ||
774 | char sum = 0, checksum = 0; | ||
775 | |||
776 | sum += 0x82 + 0x002 + 0x00D; | ||
777 | hdmi_write_reg(HDMI_CORE_AV_AVI_TYPE, 0x082); | ||
778 | hdmi_write_reg(HDMI_CORE_AV_AVI_VERS, 0x002); | ||
779 | hdmi_write_reg(HDMI_CORE_AV_AVI_LEN, 0x00D); | ||
780 | |||
781 | val = (info_avi.db1_format << 5) | | ||
782 | (info_avi.db1_active_info << 4) | | ||
783 | (info_avi.db1_bar_info_dv << 2) | | ||
784 | (info_avi.db1_scan_info); | ||
785 | hdmi_write_reg(HDMI_CORE_AV_AVI_DBYTE(0), val); | ||
786 | sum += val; | ||
787 | |||
788 | val = (info_avi.db2_colorimetry << 6) | | ||
789 | (info_avi.db2_aspect_ratio << 4) | | ||
790 | (info_avi.db2_active_fmt_ar); | ||
791 | hdmi_write_reg(HDMI_CORE_AV_AVI_DBYTE(1), val); | ||
792 | sum += val; | ||
793 | |||
794 | val = (info_avi.db3_itc << 7) | | ||
795 | (info_avi.db3_ec << 4) | | ||
796 | (info_avi.db3_q_range << 2) | | ||
797 | (info_avi.db3_nup_scaling); | ||
798 | hdmi_write_reg(HDMI_CORE_AV_AVI_DBYTE(2), val); | ||
799 | sum += val; | ||
800 | |||
801 | hdmi_write_reg(HDMI_CORE_AV_AVI_DBYTE(3), info_avi.db4_videocode); | ||
802 | sum += info_avi.db4_videocode; | ||
803 | |||
804 | val = info_avi.db5_pixel_repeat; | ||
805 | hdmi_write_reg(HDMI_CORE_AV_AVI_DBYTE(4), val); | ||
806 | sum += val; | ||
807 | |||
808 | val = info_avi.db6_7_line_eoftop & 0x00FF; | ||
809 | hdmi_write_reg(HDMI_CORE_AV_AVI_DBYTE(5), val); | ||
810 | sum += val; | ||
811 | |||
812 | val = ((info_avi.db6_7_line_eoftop >> 8) & 0x00FF); | ||
813 | hdmi_write_reg(HDMI_CORE_AV_AVI_DBYTE(6), val); | ||
814 | sum += val; | ||
815 | |||
816 | val = info_avi.db8_9_line_sofbottom & 0x00FF; | ||
817 | hdmi_write_reg(HDMI_CORE_AV_AVI_DBYTE(7), val); | ||
818 | sum += val; | ||
819 | |||
820 | val = ((info_avi.db8_9_line_sofbottom >> 8) & 0x00FF); | ||
821 | hdmi_write_reg(HDMI_CORE_AV_AVI_DBYTE(8), val); | ||
822 | sum += val; | ||
823 | |||
824 | val = info_avi.db10_11_pixel_eofleft & 0x00FF; | ||
825 | hdmi_write_reg(HDMI_CORE_AV_AVI_DBYTE(9), val); | ||
826 | sum += val; | ||
827 | |||
828 | val = ((info_avi.db10_11_pixel_eofleft >> 8) & 0x00FF); | ||
829 | hdmi_write_reg(HDMI_CORE_AV_AVI_DBYTE(10), val); | ||
830 | sum += val; | ||
831 | |||
832 | val = info_avi.db12_13_pixel_sofright & 0x00FF; | ||
833 | hdmi_write_reg(HDMI_CORE_AV_AVI_DBYTE(11), val); | ||
834 | sum += val; | ||
835 | |||
836 | val = ((info_avi.db12_13_pixel_sofright >> 8) & 0x00FF); | ||
837 | hdmi_write_reg(HDMI_CORE_AV_AVI_DBYTE(12), val); | ||
838 | sum += val; | ||
839 | |||
840 | checksum = 0x100 - sum; | ||
841 | hdmi_write_reg(HDMI_CORE_AV_AVI_CHSUM, checksum); | ||
842 | } | ||
843 | |||
844 | static void hdmi_core_av_packet_config( | ||
845 | struct hdmi_core_packet_enable_repeat repeat_cfg) | ||
846 | { | ||
847 | /* enable/repeat the infoframe */ | ||
848 | hdmi_write_reg(HDMI_CORE_AV_PB_CTRL1, | ||
849 | (repeat_cfg.audio_pkt << 5) | | ||
850 | (repeat_cfg.audio_pkt_repeat << 4) | | ||
851 | (repeat_cfg.avi_infoframe << 1) | | ||
852 | (repeat_cfg.avi_infoframe_repeat)); | ||
853 | |||
854 | /* enable/repeat the packet */ | ||
855 | hdmi_write_reg(HDMI_CORE_AV_PB_CTRL2, | ||
856 | (repeat_cfg.gen_cntrl_pkt << 3) | | ||
857 | (repeat_cfg.gen_cntrl_pkt_repeat << 2) | | ||
858 | (repeat_cfg.generic_pkt << 1) | | ||
859 | (repeat_cfg.generic_pkt_repeat)); | ||
860 | } | ||
861 | |||
862 | static void hdmi_wp_init(struct omap_video_timings *timings, | ||
863 | struct hdmi_video_format *video_fmt, | ||
864 | struct hdmi_video_interface *video_int) | ||
865 | { | ||
866 | DSSDBG("Enter hdmi_wp_init\n"); | ||
867 | |||
868 | timings->hbp = 0; | ||
869 | timings->hfp = 0; | ||
870 | timings->hsw = 0; | ||
871 | timings->vbp = 0; | ||
872 | timings->vfp = 0; | ||
873 | timings->vsw = 0; | ||
874 | |||
875 | video_fmt->packing_mode = HDMI_PACK_10b_RGB_YUV444; | ||
876 | video_fmt->y_res = 0; | ||
877 | video_fmt->x_res = 0; | ||
878 | |||
879 | video_int->vsp = 0; | ||
880 | video_int->hsp = 0; | ||
881 | |||
882 | video_int->interlacing = 0; | ||
883 | video_int->tm = 0; /* HDMI_TIMING_SLAVE */ | ||
884 | |||
885 | } | ||
886 | |||
887 | static void hdmi_wp_video_start(bool start) | ||
888 | { | ||
889 | REG_FLD_MOD(HDMI_WP_VIDEO_CFG, start, 31, 31); | ||
890 | } | ||
891 | |||
892 | static void hdmi_wp_video_init_format(struct hdmi_video_format *video_fmt, | ||
893 | struct omap_video_timings *timings, struct hdmi_config *param) | ||
894 | { | ||
895 | DSSDBG("Enter hdmi_wp_video_init_format\n"); | ||
896 | |||
897 | video_fmt->y_res = param->timings.timings.y_res; | ||
898 | video_fmt->x_res = param->timings.timings.x_res; | ||
899 | |||
900 | timings->hbp = param->timings.timings.hbp; | ||
901 | timings->hfp = param->timings.timings.hfp; | ||
902 | timings->hsw = param->timings.timings.hsw; | ||
903 | timings->vbp = param->timings.timings.vbp; | ||
904 | timings->vfp = param->timings.timings.vfp; | ||
905 | timings->vsw = param->timings.timings.vsw; | ||
906 | } | ||
907 | |||
908 | static void hdmi_wp_video_config_format( | ||
909 | struct hdmi_video_format *video_fmt) | ||
910 | { | ||
911 | u32 l = 0; | ||
912 | |||
913 | REG_FLD_MOD(HDMI_WP_VIDEO_CFG, video_fmt->packing_mode, 10, 8); | ||
914 | |||
915 | l |= FLD_VAL(video_fmt->y_res, 31, 16); | ||
916 | l |= FLD_VAL(video_fmt->x_res, 15, 0); | ||
917 | hdmi_write_reg(HDMI_WP_VIDEO_SIZE, l); | ||
918 | } | ||
919 | |||
920 | static void hdmi_wp_video_config_interface( | ||
921 | struct hdmi_video_interface *video_int) | ||
922 | { | ||
923 | u32 r; | ||
924 | DSSDBG("Enter hdmi_wp_video_config_interface\n"); | ||
925 | |||
926 | r = hdmi_read_reg(HDMI_WP_VIDEO_CFG); | ||
927 | r = FLD_MOD(r, video_int->vsp, 7, 7); | ||
928 | r = FLD_MOD(r, video_int->hsp, 6, 6); | ||
929 | r = FLD_MOD(r, video_int->interlacing, 3, 3); | ||
930 | r = FLD_MOD(r, video_int->tm, 1, 0); | ||
931 | hdmi_write_reg(HDMI_WP_VIDEO_CFG, r); | ||
932 | } | ||
933 | |||
934 | static void hdmi_wp_video_config_timing( | ||
935 | struct omap_video_timings *timings) | ||
936 | { | ||
937 | u32 timing_h = 0; | ||
938 | u32 timing_v = 0; | ||
939 | |||
940 | DSSDBG("Enter hdmi_wp_video_config_timing\n"); | ||
941 | |||
942 | timing_h |= FLD_VAL(timings->hbp, 31, 20); | ||
943 | timing_h |= FLD_VAL(timings->hfp, 19, 8); | ||
944 | timing_h |= FLD_VAL(timings->hsw, 7, 0); | ||
945 | hdmi_write_reg(HDMI_WP_VIDEO_TIMING_H, timing_h); | ||
946 | |||
947 | timing_v |= FLD_VAL(timings->vbp, 31, 20); | ||
948 | timing_v |= FLD_VAL(timings->vfp, 19, 8); | ||
949 | timing_v |= FLD_VAL(timings->vsw, 7, 0); | ||
950 | hdmi_write_reg(HDMI_WP_VIDEO_TIMING_V, timing_v); | ||
951 | } | ||
952 | |||
953 | static void hdmi_basic_configure(struct hdmi_config *cfg) | ||
954 | { | ||
955 | /* HDMI */ | ||
956 | struct omap_video_timings video_timing; | ||
957 | struct hdmi_video_format video_format; | ||
958 | struct hdmi_video_interface video_interface; | ||
959 | /* HDMI core */ | ||
960 | struct hdmi_core_infoframe_avi avi_cfg; | ||
961 | struct hdmi_core_video_config v_core_cfg; | ||
962 | struct hdmi_core_packet_enable_repeat repeat_cfg; | ||
963 | |||
964 | hdmi_wp_init(&video_timing, &video_format, | ||
965 | &video_interface); | ||
966 | |||
967 | hdmi_core_init(&v_core_cfg, | ||
968 | &avi_cfg, | ||
969 | &repeat_cfg); | ||
970 | |||
971 | hdmi_wp_video_init_format(&video_format, | ||
972 | &video_timing, cfg); | ||
973 | |||
974 | hdmi_wp_video_config_timing(&video_timing); | ||
975 | |||
976 | /* video config */ | ||
977 | video_format.packing_mode = HDMI_PACK_24b_RGB_YUV444_YUV422; | ||
978 | |||
979 | hdmi_wp_video_config_format(&video_format); | ||
980 | |||
981 | video_interface.vsp = cfg->timings.vsync_pol; | ||
982 | video_interface.hsp = cfg->timings.hsync_pol; | ||
983 | video_interface.interlacing = cfg->interlace; | ||
984 | video_interface.tm = 1 ; /* HDMI_TIMING_MASTER_24BIT */ | ||
985 | |||
986 | hdmi_wp_video_config_interface(&video_interface); | ||
987 | |||
988 | /* | ||
989 | * configure core video part | ||
990 | * set software reset in the core | ||
991 | */ | ||
992 | hdmi_core_swreset_assert(); | ||
993 | |||
994 | /* power down off */ | ||
995 | hdmi_core_powerdown_disable(); | ||
996 | |||
997 | v_core_cfg.pkt_mode = HDMI_PACKETMODE24BITPERPIXEL; | ||
998 | v_core_cfg.hdmi_dvi = cfg->cm.mode; | ||
999 | |||
1000 | hdmi_core_video_config(&v_core_cfg); | ||
1001 | |||
1002 | /* release software reset in the core */ | ||
1003 | hdmi_core_swreset_release(); | ||
1004 | |||
1005 | /* | ||
1006 | * configure packet | ||
1007 | * info frame video see doc CEA861-D page 65 | ||
1008 | */ | ||
1009 | avi_cfg.db1_format = HDMI_INFOFRAME_AVI_DB1Y_RGB; | ||
1010 | avi_cfg.db1_active_info = | ||
1011 | HDMI_INFOFRAME_AVI_DB1A_ACTIVE_FORMAT_OFF; | ||
1012 | avi_cfg.db1_bar_info_dv = HDMI_INFOFRAME_AVI_DB1B_NO; | ||
1013 | avi_cfg.db1_scan_info = HDMI_INFOFRAME_AVI_DB1S_0; | ||
1014 | avi_cfg.db2_colorimetry = HDMI_INFOFRAME_AVI_DB2C_NO; | ||
1015 | avi_cfg.db2_aspect_ratio = HDMI_INFOFRAME_AVI_DB2M_NO; | ||
1016 | avi_cfg.db2_active_fmt_ar = HDMI_INFOFRAME_AVI_DB2R_SAME; | ||
1017 | avi_cfg.db3_itc = HDMI_INFOFRAME_AVI_DB3ITC_NO; | ||
1018 | avi_cfg.db3_ec = HDMI_INFOFRAME_AVI_DB3EC_XVYUV601; | ||
1019 | avi_cfg.db3_q_range = HDMI_INFOFRAME_AVI_DB3Q_DEFAULT; | ||
1020 | avi_cfg.db3_nup_scaling = HDMI_INFOFRAME_AVI_DB3SC_NO; | ||
1021 | avi_cfg.db4_videocode = cfg->cm.code; | ||
1022 | avi_cfg.db5_pixel_repeat = HDMI_INFOFRAME_AVI_DB5PR_NO; | ||
1023 | avi_cfg.db6_7_line_eoftop = 0; | ||
1024 | avi_cfg.db8_9_line_sofbottom = 0; | ||
1025 | avi_cfg.db10_11_pixel_eofleft = 0; | ||
1026 | avi_cfg.db12_13_pixel_sofright = 0; | ||
1027 | |||
1028 | hdmi_core_aux_infoframe_avi_config(avi_cfg); | ||
1029 | |||
1030 | /* enable/repeat the infoframe */ | ||
1031 | repeat_cfg.avi_infoframe = HDMI_PACKETENABLE; | ||
1032 | repeat_cfg.avi_infoframe_repeat = HDMI_PACKETREPEATON; | ||
1033 | /* wakeup */ | ||
1034 | repeat_cfg.audio_pkt = HDMI_PACKETENABLE; | ||
1035 | repeat_cfg.audio_pkt_repeat = HDMI_PACKETREPEATON; | ||
1036 | hdmi_core_av_packet_config(repeat_cfg); | ||
1037 | } | ||
1038 | |||
1039 | static void update_hdmi_timings(struct hdmi_config *cfg, | ||
1040 | struct omap_video_timings *timings, int code) | ||
1041 | { | ||
1042 | cfg->timings.timings.x_res = timings->x_res; | ||
1043 | cfg->timings.timings.y_res = timings->y_res; | ||
1044 | cfg->timings.timings.hbp = timings->hbp; | ||
1045 | cfg->timings.timings.hfp = timings->hfp; | ||
1046 | cfg->timings.timings.hsw = timings->hsw; | ||
1047 | cfg->timings.timings.vbp = timings->vbp; | ||
1048 | cfg->timings.timings.vfp = timings->vfp; | ||
1049 | cfg->timings.timings.vsw = timings->vsw; | ||
1050 | cfg->timings.timings.pixel_clock = timings->pixel_clock; | ||
1051 | cfg->timings.vsync_pol = cea_vesa_timings[code].vsync_pol; | ||
1052 | cfg->timings.hsync_pol = cea_vesa_timings[code].hsync_pol; | ||
1053 | } | ||
1054 | |||
1055 | static void hdmi_compute_pll(unsigned long clkin, int phy, | ||
1056 | int n, struct hdmi_pll_info *pi) | ||
1057 | { | ||
1058 | unsigned long refclk; | ||
1059 | u32 mf; | ||
1060 | |||
1061 | /* | ||
1062 | * Input clock is predivided by N + 1 | ||
1063 | * out put of which is reference clk | ||
1064 | */ | ||
1065 | refclk = clkin / (n + 1); | ||
1066 | pi->regn = n; | ||
1067 | |||
1068 | /* | ||
1069 | * multiplier is pixel_clk/ref_clk | ||
1070 | * Multiplying by 100 to avoid fractional part removal | ||
1071 | */ | ||
1072 | pi->regm = (phy * 100/(refclk))/100; | ||
1073 | pi->regm2 = 1; | ||
1074 | |||
1075 | /* | ||
1076 | * fractional multiplier is remainder of the difference between | ||
1077 | * multiplier and actual phy(required pixel clock thus should be | ||
1078 | * multiplied by 2^18(262144) divided by the reference clock | ||
1079 | */ | ||
1080 | mf = (phy - pi->regm * refclk) * 262144; | ||
1081 | pi->regmf = mf/(refclk); | ||
1082 | |||
1083 | /* | ||
1084 | * Dcofreq should be set to 1 if required pixel clock | ||
1085 | * is greater than 1000MHz | ||
1086 | */ | ||
1087 | pi->dcofreq = phy > 1000 * 100; | ||
1088 | pi->regsd = ((pi->regm * clkin / 10) / ((n + 1) * 250) + 5) / 10; | ||
1089 | |||
1090 | DSSDBG("M = %d Mf = %d\n", pi->regm, pi->regmf); | ||
1091 | DSSDBG("range = %d sd = %d\n", pi->dcofreq, pi->regsd); | ||
1092 | } | ||
1093 | |||
1094 | static void hdmi_enable_clocks(int enable) | ||
1095 | { | ||
1096 | if (enable) | ||
1097 | dss_clk_enable(DSS_CLK_ICK | DSS_CLK_FCK | | ||
1098 | DSS_CLK_SYSCK | DSS_CLK_VIDFCK); | ||
1099 | else | ||
1100 | dss_clk_disable(DSS_CLK_ICK | DSS_CLK_FCK | | ||
1101 | DSS_CLK_SYSCK | DSS_CLK_VIDFCK); | ||
1102 | } | ||
1103 | |||
1104 | static int hdmi_power_on(struct omap_dss_device *dssdev) | ||
1105 | { | ||
1106 | int r, code = 0; | ||
1107 | struct hdmi_pll_info pll_data; | ||
1108 | struct omap_video_timings *p; | ||
1109 | int clkin, n, phy; | ||
1110 | |||
1111 | hdmi_enable_clocks(1); | ||
1112 | |||
1113 | dispc_enable_channel(OMAP_DSS_CHANNEL_DIGIT, 0); | ||
1114 | |||
1115 | p = &dssdev->panel.timings; | ||
1116 | |||
1117 | DSSDBG("hdmi_power_on x_res= %d y_res = %d\n", | ||
1118 | dssdev->panel.timings.x_res, | ||
1119 | dssdev->panel.timings.y_res); | ||
1120 | |||
1121 | if (!hdmi.custom_set) { | ||
1122 | DSSDBG("Read EDID as no EDID is not set on poweron\n"); | ||
1123 | hdmi_read_edid(p); | ||
1124 | } | ||
1125 | code = get_timings_index(); | ||
1126 | dssdev->panel.timings = cea_vesa_timings[code].timings; | ||
1127 | update_hdmi_timings(&hdmi.cfg, p, code); | ||
1128 | |||
1129 | clkin = 3840; /* 38.4 MHz */ | ||
1130 | n = 15; /* this is a constant for our math */ | ||
1131 | phy = p->pixel_clock; | ||
1132 | |||
1133 | hdmi_compute_pll(clkin, phy, n, &pll_data); | ||
1134 | |||
1135 | hdmi_wp_video_start(0); | ||
1136 | |||
1137 | /* config the PLL and PHY first */ | ||
1138 | r = hdmi_pll_program(&pll_data); | ||
1139 | if (r) { | ||
1140 | DSSDBG("Failed to lock PLL\n"); | ||
1141 | goto err; | ||
1142 | } | ||
1143 | |||
1144 | r = hdmi_phy_init(); | ||
1145 | if (r) { | ||
1146 | DSSDBG("Failed to start PHY\n"); | ||
1147 | goto err; | ||
1148 | } | ||
1149 | |||
1150 | hdmi.cfg.cm.mode = hdmi.mode; | ||
1151 | hdmi.cfg.cm.code = hdmi.code; | ||
1152 | hdmi_basic_configure(&hdmi.cfg); | ||
1153 | |||
1154 | /* Make selection of HDMI in DSS */ | ||
1155 | dss_select_hdmi_venc_clk_source(DSS_HDMI_M_PCLK); | ||
1156 | |||
1157 | /* Select the dispc clock source as PRCM clock, to ensure that it is not | ||
1158 | * DSI PLL source as the clock selected by DSI PLL might not be | ||
1159 | * sufficient for the resolution selected / that can be changed | ||
1160 | * dynamically by user. This can be moved to single location , say | ||
1161 | * Boardfile. | ||
1162 | */ | ||
1163 | dss_select_dispc_clk_source(DSS_CLK_SRC_FCK); | ||
1164 | |||
1165 | /* bypass TV gamma table */ | ||
1166 | dispc_enable_gamma_table(0); | ||
1167 | |||
1168 | /* tv size */ | ||
1169 | dispc_set_digit_size(dssdev->panel.timings.x_res, | ||
1170 | dssdev->panel.timings.y_res); | ||
1171 | |||
1172 | dispc_enable_channel(OMAP_DSS_CHANNEL_DIGIT, 1); | ||
1173 | |||
1174 | hdmi_wp_video_start(1); | ||
1175 | |||
1176 | return 0; | ||
1177 | err: | ||
1178 | hdmi_enable_clocks(0); | ||
1179 | return -EIO; | ||
1180 | } | ||
1181 | |||
1182 | static void hdmi_power_off(struct omap_dss_device *dssdev) | ||
1183 | { | ||
1184 | dispc_enable_channel(OMAP_DSS_CHANNEL_DIGIT, 0); | ||
1185 | |||
1186 | hdmi_wp_video_start(0); | ||
1187 | hdmi_phy_off(); | ||
1188 | hdmi_set_pll_pwr(HDMI_PLLPWRCMD_ALLOFF); | ||
1189 | hdmi_enable_clocks(0); | ||
1190 | |||
1191 | hdmi.edid_set = 0; | ||
1192 | } | ||
1193 | |||
1194 | int omapdss_hdmi_display_check_timing(struct omap_dss_device *dssdev, | ||
1195 | struct omap_video_timings *timings) | ||
1196 | { | ||
1197 | struct hdmi_cm cm; | ||
1198 | |||
1199 | cm = hdmi_get_code(timings); | ||
1200 | if (cm.code == -1) { | ||
1201 | DSSERR("Invalid timing entered\n"); | ||
1202 | return -EINVAL; | ||
1203 | } | ||
1204 | |||
1205 | return 0; | ||
1206 | |||
1207 | } | ||
1208 | |||
1209 | void omapdss_hdmi_display_set_timing(struct omap_dss_device *dssdev) | ||
1210 | { | ||
1211 | struct hdmi_cm cm; | ||
1212 | |||
1213 | hdmi.custom_set = 1; | ||
1214 | cm = hdmi_get_code(&dssdev->panel.timings); | ||
1215 | hdmi.code = cm.code; | ||
1216 | hdmi.mode = cm.mode; | ||
1217 | omapdss_hdmi_display_enable(dssdev); | ||
1218 | hdmi.custom_set = 0; | ||
1219 | } | ||
1220 | |||
1221 | int omapdss_hdmi_display_enable(struct omap_dss_device *dssdev) | ||
1222 | { | ||
1223 | int r = 0; | ||
1224 | |||
1225 | DSSDBG("ENTER hdmi_display_enable\n"); | ||
1226 | |||
1227 | mutex_lock(&hdmi.lock); | ||
1228 | |||
1229 | r = omap_dss_start_device(dssdev); | ||
1230 | if (r) { | ||
1231 | DSSERR("failed to start device\n"); | ||
1232 | goto err0; | ||
1233 | } | ||
1234 | |||
1235 | if (dssdev->platform_enable) { | ||
1236 | r = dssdev->platform_enable(dssdev); | ||
1237 | if (r) { | ||
1238 | DSSERR("failed to enable GPIO's\n"); | ||
1239 | goto err1; | ||
1240 | } | ||
1241 | } | ||
1242 | |||
1243 | r = hdmi_power_on(dssdev); | ||
1244 | if (r) { | ||
1245 | DSSERR("failed to power on device\n"); | ||
1246 | goto err2; | ||
1247 | } | ||
1248 | |||
1249 | mutex_unlock(&hdmi.lock); | ||
1250 | return 0; | ||
1251 | |||
1252 | err2: | ||
1253 | if (dssdev->platform_disable) | ||
1254 | dssdev->platform_disable(dssdev); | ||
1255 | err1: | ||
1256 | omap_dss_stop_device(dssdev); | ||
1257 | err0: | ||
1258 | mutex_unlock(&hdmi.lock); | ||
1259 | return r; | ||
1260 | } | ||
1261 | |||
1262 | void omapdss_hdmi_display_disable(struct omap_dss_device *dssdev) | ||
1263 | { | ||
1264 | DSSDBG("Enter hdmi_display_disable\n"); | ||
1265 | |||
1266 | mutex_lock(&hdmi.lock); | ||
1267 | |||
1268 | hdmi_power_off(dssdev); | ||
1269 | |||
1270 | if (dssdev->platform_disable) | ||
1271 | dssdev->platform_disable(dssdev); | ||
1272 | |||
1273 | omap_dss_stop_device(dssdev); | ||
1274 | |||
1275 | mutex_unlock(&hdmi.lock); | ||
1276 | } | ||
1277 | |||
1278 | /* HDMI HW IP initialisation */ | ||
1279 | static int omapdss_hdmihw_probe(struct platform_device *pdev) | ||
1280 | { | ||
1281 | struct resource *hdmi_mem; | ||
1282 | |||
1283 | hdmi.pdata = pdev->dev.platform_data; | ||
1284 | hdmi.pdev = pdev; | ||
1285 | |||
1286 | mutex_init(&hdmi.lock); | ||
1287 | |||
1288 | hdmi_mem = platform_get_resource(hdmi.pdev, IORESOURCE_MEM, 0); | ||
1289 | if (!hdmi_mem) { | ||
1290 | DSSERR("can't get IORESOURCE_MEM HDMI\n"); | ||
1291 | return -EINVAL; | ||
1292 | } | ||
1293 | |||
1294 | /* Base address taken from platform */ | ||
1295 | hdmi.base_wp = ioremap(hdmi_mem->start, resource_size(hdmi_mem)); | ||
1296 | if (!hdmi.base_wp) { | ||
1297 | DSSERR("can't ioremap WP\n"); | ||
1298 | return -ENOMEM; | ||
1299 | } | ||
1300 | |||
1301 | hdmi_panel_init(); | ||
1302 | |||
1303 | return 0; | ||
1304 | } | ||
1305 | |||
1306 | static int omapdss_hdmihw_remove(struct platform_device *pdev) | ||
1307 | { | ||
1308 | hdmi_panel_exit(); | ||
1309 | |||
1310 | iounmap(hdmi.base_wp); | ||
1311 | |||
1312 | return 0; | ||
1313 | } | ||
1314 | |||
1315 | static struct platform_driver omapdss_hdmihw_driver = { | ||
1316 | .probe = omapdss_hdmihw_probe, | ||
1317 | .remove = omapdss_hdmihw_remove, | ||
1318 | .driver = { | ||
1319 | .name = "omapdss_hdmi", | ||
1320 | .owner = THIS_MODULE, | ||
1321 | }, | ||
1322 | }; | ||
1323 | |||
1324 | int hdmi_init_platform_driver(void) | ||
1325 | { | ||
1326 | return platform_driver_register(&omapdss_hdmihw_driver); | ||
1327 | } | ||
1328 | |||
1329 | void hdmi_uninit_platform_driver(void) | ||
1330 | { | ||
1331 | return platform_driver_unregister(&omapdss_hdmihw_driver); | ||
1332 | } | ||
diff --git a/drivers/video/omap2/dss/hdmi.h b/drivers/video/omap2/dss/hdmi.h new file mode 100644 index 000000000000..9887ab96da3c --- /dev/null +++ b/drivers/video/omap2/dss/hdmi.h | |||
@@ -0,0 +1,415 @@ | |||
1 | /* | ||
2 | * hdmi.h | ||
3 | * | ||
4 | * HDMI driver definition for TI OMAP4 processors. | ||
5 | * | ||
6 | * Copyright (C) 2010-2011 Texas Instruments Incorporated - http://www.ti.com/ | ||
7 | * | ||
8 | * This program is free software; you can redistribute it and/or modify it | ||
9 | * under the terms of the GNU General Public License version 2 as published by | ||
10 | * the Free Software Foundation. | ||
11 | * | ||
12 | * This program is distributed in the hope that it will be useful, but WITHOUT | ||
13 | * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or | ||
14 | * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for | ||
15 | * more details. | ||
16 | * | ||
17 | * You should have received a copy of the GNU General Public License along with | ||
18 | * this program. If not, see <http://www.gnu.org/licenses/>. | ||
19 | */ | ||
20 | |||
21 | #ifndef _OMAP4_DSS_HDMI_H_ | ||
22 | #define _OMAP4_DSS_HDMI_H_ | ||
23 | |||
24 | #include <linux/string.h> | ||
25 | #include <plat/display.h> | ||
26 | |||
27 | #define HDMI_WP 0x0 | ||
28 | #define HDMI_CORE_SYS 0x400 | ||
29 | #define HDMI_CORE_AV 0x900 | ||
30 | #define HDMI_PLLCTRL 0x200 | ||
31 | #define HDMI_PHY 0x300 | ||
32 | |||
33 | struct hdmi_reg { u16 idx; }; | ||
34 | |||
35 | #define HDMI_REG(idx) ((const struct hdmi_reg) { idx }) | ||
36 | |||
37 | /* HDMI Wrapper */ | ||
38 | #define HDMI_WP_REG(idx) HDMI_REG(HDMI_WP + idx) | ||
39 | |||
40 | #define HDMI_WP_REVISION HDMI_WP_REG(0x0) | ||
41 | #define HDMI_WP_SYSCONFIG HDMI_WP_REG(0x10) | ||
42 | #define HDMI_WP_IRQSTATUS_RAW HDMI_WP_REG(0x24) | ||
43 | #define HDMI_WP_IRQSTATUS HDMI_WP_REG(0x28) | ||
44 | #define HDMI_WP_PWR_CTRL HDMI_WP_REG(0x40) | ||
45 | #define HDMI_WP_IRQENABLE_SET HDMI_WP_REG(0x2C) | ||
46 | #define HDMI_WP_VIDEO_CFG HDMI_WP_REG(0x50) | ||
47 | #define HDMI_WP_VIDEO_SIZE HDMI_WP_REG(0x60) | ||
48 | #define HDMI_WP_VIDEO_TIMING_H HDMI_WP_REG(0x68) | ||
49 | #define HDMI_WP_VIDEO_TIMING_V HDMI_WP_REG(0x6C) | ||
50 | #define HDMI_WP_WP_CLK HDMI_WP_REG(0x70) | ||
51 | |||
52 | /* HDMI IP Core System */ | ||
53 | #define HDMI_CORE_SYS_REG(idx) HDMI_REG(HDMI_CORE_SYS + idx) | ||
54 | |||
55 | #define HDMI_CORE_SYS_VND_IDL HDMI_CORE_SYS_REG(0x0) | ||
56 | #define HDMI_CORE_SYS_DEV_IDL HDMI_CORE_SYS_REG(0x8) | ||
57 | #define HDMI_CORE_SYS_DEV_IDH HDMI_CORE_SYS_REG(0xC) | ||
58 | #define HDMI_CORE_SYS_DEV_REV HDMI_CORE_SYS_REG(0x10) | ||
59 | #define HDMI_CORE_SYS_SRST HDMI_CORE_SYS_REG(0x14) | ||
60 | #define HDMI_CORE_CTRL1 HDMI_CORE_SYS_REG(0x20) | ||
61 | #define HDMI_CORE_SYS_SYS_STAT HDMI_CORE_SYS_REG(0x24) | ||
62 | #define HDMI_CORE_SYS_VID_ACEN HDMI_CORE_SYS_REG(0x124) | ||
63 | #define HDMI_CORE_SYS_VID_MODE HDMI_CORE_SYS_REG(0x128) | ||
64 | #define HDMI_CORE_SYS_INTR_STATE HDMI_CORE_SYS_REG(0x1C0) | ||
65 | #define HDMI_CORE_SYS_INTR1 HDMI_CORE_SYS_REG(0x1C4) | ||
66 | #define HDMI_CORE_SYS_INTR2 HDMI_CORE_SYS_REG(0x1C8) | ||
67 | #define HDMI_CORE_SYS_INTR3 HDMI_CORE_SYS_REG(0x1CC) | ||
68 | #define HDMI_CORE_SYS_INTR4 HDMI_CORE_SYS_REG(0x1D0) | ||
69 | #define HDMI_CORE_SYS_UMASK1 HDMI_CORE_SYS_REG(0x1D4) | ||
70 | #define HDMI_CORE_SYS_TMDS_CTRL HDMI_CORE_SYS_REG(0x208) | ||
71 | #define HDMI_CORE_SYS_DE_DLY HDMI_CORE_SYS_REG(0xC8) | ||
72 | #define HDMI_CORE_SYS_DE_CTRL HDMI_CORE_SYS_REG(0xCC) | ||
73 | #define HDMI_CORE_SYS_DE_TOP HDMI_CORE_SYS_REG(0xD0) | ||
74 | #define HDMI_CORE_SYS_DE_CNTL HDMI_CORE_SYS_REG(0xD8) | ||
75 | #define HDMI_CORE_SYS_DE_CNTH HDMI_CORE_SYS_REG(0xDC) | ||
76 | #define HDMI_CORE_SYS_DE_LINL HDMI_CORE_SYS_REG(0xE0) | ||
77 | #define HDMI_CORE_SYS_DE_LINH_1 HDMI_CORE_SYS_REG(0xE4) | ||
78 | #define HDMI_CORE_CTRL1_VEN_FOLLOWVSYNC 0x1 | ||
79 | #define HDMI_CORE_CTRL1_HEN_FOLLOWHSYNC 0x1 | ||
80 | #define HDMI_CORE_CTRL1_BSEL_24BITBUS 0x1 | ||
81 | #define HDMI_CORE_CTRL1_EDGE_RISINGEDGE 0x1 | ||
82 | |||
83 | /* HDMI DDC E-DID */ | ||
84 | #define HDMI_CORE_DDC_CMD HDMI_CORE_SYS_REG(0x3CC) | ||
85 | #define HDMI_CORE_DDC_STATUS HDMI_CORE_SYS_REG(0x3C8) | ||
86 | #define HDMI_CORE_DDC_ADDR HDMI_CORE_SYS_REG(0x3B4) | ||
87 | #define HDMI_CORE_DDC_OFFSET HDMI_CORE_SYS_REG(0x3BC) | ||
88 | #define HDMI_CORE_DDC_COUNT1 HDMI_CORE_SYS_REG(0x3C0) | ||
89 | #define HDMI_CORE_DDC_COUNT2 HDMI_CORE_SYS_REG(0x3C4) | ||
90 | #define HDMI_CORE_DDC_DATA HDMI_CORE_SYS_REG(0x3D0) | ||
91 | #define HDMI_CORE_DDC_SEGM HDMI_CORE_SYS_REG(0x3B8) | ||
92 | |||
93 | /* HDMI IP Core Audio Video */ | ||
94 | #define HDMI_CORE_AV_REG(idx) HDMI_REG(HDMI_CORE_AV + idx) | ||
95 | |||
96 | #define HDMI_CORE_AV_HDMI_CTRL HDMI_CORE_AV_REG(0xBC) | ||
97 | #define HDMI_CORE_AV_DPD HDMI_CORE_AV_REG(0xF4) | ||
98 | #define HDMI_CORE_AV_PB_CTRL1 HDMI_CORE_AV_REG(0xF8) | ||
99 | #define HDMI_CORE_AV_PB_CTRL2 HDMI_CORE_AV_REG(0xFC) | ||
100 | #define HDMI_CORE_AV_AVI_TYPE HDMI_CORE_AV_REG(0x100) | ||
101 | #define HDMI_CORE_AV_AVI_VERS HDMI_CORE_AV_REG(0x104) | ||
102 | #define HDMI_CORE_AV_AVI_LEN HDMI_CORE_AV_REG(0x108) | ||
103 | #define HDMI_CORE_AV_AVI_CHSUM HDMI_CORE_AV_REG(0x10C) | ||
104 | #define HDMI_CORE_AV_AVI_DBYTE(n) HDMI_CORE_AV_REG(n * 4 + 0x110) | ||
105 | #define HDMI_CORE_AV_AVI_DBYTE_NELEMS HDMI_CORE_AV_REG(15) | ||
106 | #define HDMI_CORE_AV_SPD_DBYTE HDMI_CORE_AV_REG(0x190) | ||
107 | #define HDMI_CORE_AV_SPD_DBYTE_NELEMS HDMI_CORE_AV_REG(27) | ||
108 | #define HDMI_CORE_AV_MPEG_DBYTE HDMI_CORE_AV_REG(0x290) | ||
109 | #define HDMI_CORE_AV_MPEG_DBYTE_NELEMS HDMI_CORE_AV_REG(27) | ||
110 | #define HDMI_CORE_AV_GEN_DBYTE HDMI_CORE_AV_REG(0x300) | ||
111 | #define HDMI_CORE_AV_GEN_DBYTE_NELEMS HDMI_CORE_AV_REG(31) | ||
112 | #define HDMI_CORE_AV_GEN2_DBYTE HDMI_CORE_AV_REG(0x380) | ||
113 | #define HDMI_CORE_AV_GEN2_DBYTE_NELEMS HDMI_CORE_AV_REG(31) | ||
114 | #define HDMI_CORE_AV_ACR_CTRL HDMI_CORE_AV_REG(0x4) | ||
115 | #define HDMI_CORE_AV_FREQ_SVAL HDMI_CORE_AV_REG(0x8) | ||
116 | #define HDMI_CORE_AV_N_SVAL1 HDMI_CORE_AV_REG(0xC) | ||
117 | #define HDMI_CORE_AV_N_SVAL2 HDMI_CORE_AV_REG(0x10) | ||
118 | #define HDMI_CORE_AV_N_SVAL3 HDMI_CORE_AV_REG(0x14) | ||
119 | #define HDMI_CORE_AV_CTS_SVAL1 HDMI_CORE_AV_REG(0x18) | ||
120 | #define HDMI_CORE_AV_CTS_SVAL2 HDMI_CORE_AV_REG(0x1C) | ||
121 | #define HDMI_CORE_AV_CTS_SVAL3 HDMI_CORE_AV_REG(0x20) | ||
122 | #define HDMI_CORE_AV_CTS_HVAL1 HDMI_CORE_AV_REG(0x24) | ||
123 | #define HDMI_CORE_AV_CTS_HVAL2 HDMI_CORE_AV_REG(0x28) | ||
124 | #define HDMI_CORE_AV_CTS_HVAL3 HDMI_CORE_AV_REG(0x2C) | ||
125 | #define HDMI_CORE_AV_AUD_MODE HDMI_CORE_AV_REG(0x50) | ||
126 | #define HDMI_CORE_AV_SPDIF_CTRL HDMI_CORE_AV_REG(0x54) | ||
127 | #define HDMI_CORE_AV_HW_SPDIF_FS HDMI_CORE_AV_REG(0x60) | ||
128 | #define HDMI_CORE_AV_SWAP_I2S HDMI_CORE_AV_REG(0x64) | ||
129 | #define HDMI_CORE_AV_SPDIF_ERTH HDMI_CORE_AV_REG(0x6C) | ||
130 | #define HDMI_CORE_AV_I2S_IN_MAP HDMI_CORE_AV_REG(0x70) | ||
131 | #define HDMI_CORE_AV_I2S_IN_CTRL HDMI_CORE_AV_REG(0x74) | ||
132 | #define HDMI_CORE_AV_I2S_CHST0 HDMI_CORE_AV_REG(0x78) | ||
133 | #define HDMI_CORE_AV_I2S_CHST1 HDMI_CORE_AV_REG(0x7C) | ||
134 | #define HDMI_CORE_AV_I2S_CHST2 HDMI_CORE_AV_REG(0x80) | ||
135 | #define HDMI_CORE_AV_I2S_CHST4 HDMI_CORE_AV_REG(0x84) | ||
136 | #define HDMI_CORE_AV_I2S_CHST5 HDMI_CORE_AV_REG(0x88) | ||
137 | #define HDMI_CORE_AV_ASRC HDMI_CORE_AV_REG(0x8C) | ||
138 | #define HDMI_CORE_AV_I2S_IN_LEN HDMI_CORE_AV_REG(0x90) | ||
139 | #define HDMI_CORE_AV_HDMI_CTRL HDMI_CORE_AV_REG(0xBC) | ||
140 | #define HDMI_CORE_AV_AUDO_TXSTAT HDMI_CORE_AV_REG(0xC0) | ||
141 | #define HDMI_CORE_AV_AUD_PAR_BUSCLK_1 HDMI_CORE_AV_REG(0xCC) | ||
142 | #define HDMI_CORE_AV_AUD_PAR_BUSCLK_2 HDMI_CORE_AV_REG(0xD0) | ||
143 | #define HDMI_CORE_AV_AUD_PAR_BUSCLK_3 HDMI_CORE_AV_REG(0xD4) | ||
144 | #define HDMI_CORE_AV_TEST_TXCTRL HDMI_CORE_AV_REG(0xF0) | ||
145 | #define HDMI_CORE_AV_DPD HDMI_CORE_AV_REG(0xF4) | ||
146 | #define HDMI_CORE_AV_PB_CTRL1 HDMI_CORE_AV_REG(0xF8) | ||
147 | #define HDMI_CORE_AV_PB_CTRL2 HDMI_CORE_AV_REG(0xFC) | ||
148 | #define HDMI_CORE_AV_AVI_TYPE HDMI_CORE_AV_REG(0x100) | ||
149 | #define HDMI_CORE_AV_AVI_VERS HDMI_CORE_AV_REG(0x104) | ||
150 | #define HDMI_CORE_AV_AVI_LEN HDMI_CORE_AV_REG(0x108) | ||
151 | #define HDMI_CORE_AV_AVI_CHSUM HDMI_CORE_AV_REG(0x10C) | ||
152 | #define HDMI_CORE_AV_SPD_TYPE HDMI_CORE_AV_REG(0x180) | ||
153 | #define HDMI_CORE_AV_SPD_VERS HDMI_CORE_AV_REG(0x184) | ||
154 | #define HDMI_CORE_AV_SPD_LEN HDMI_CORE_AV_REG(0x188) | ||
155 | #define HDMI_CORE_AV_SPD_CHSUM HDMI_CORE_AV_REG(0x18C) | ||
156 | #define HDMI_CORE_AV_MPEG_TYPE HDMI_CORE_AV_REG(0x280) | ||
157 | #define HDMI_CORE_AV_MPEG_VERS HDMI_CORE_AV_REG(0x284) | ||
158 | #define HDMI_CORE_AV_MPEG_LEN HDMI_CORE_AV_REG(0x288) | ||
159 | #define HDMI_CORE_AV_MPEG_CHSUM HDMI_CORE_AV_REG(0x28C) | ||
160 | #define HDMI_CORE_AV_CP_BYTE1 HDMI_CORE_AV_REG(0x37C) | ||
161 | #define HDMI_CORE_AV_CEC_ADDR_ID HDMI_CORE_AV_REG(0x3FC) | ||
162 | #define HDMI_CORE_AV_SPD_DBYTE_ELSIZE 0x4 | ||
163 | #define HDMI_CORE_AV_GEN2_DBYTE_ELSIZE 0x4 | ||
164 | #define HDMI_CORE_AV_MPEG_DBYTE_ELSIZE 0x4 | ||
165 | #define HDMI_CORE_AV_GEN_DBYTE_ELSIZE 0x4 | ||
166 | |||
167 | /* PLL */ | ||
168 | #define HDMI_PLL_REG(idx) HDMI_REG(HDMI_PLLCTRL + idx) | ||
169 | |||
170 | #define PLLCTRL_PLL_CONTROL HDMI_PLL_REG(0x0) | ||
171 | #define PLLCTRL_PLL_STATUS HDMI_PLL_REG(0x4) | ||
172 | #define PLLCTRL_PLL_GO HDMI_PLL_REG(0x8) | ||
173 | #define PLLCTRL_CFG1 HDMI_PLL_REG(0xC) | ||
174 | #define PLLCTRL_CFG2 HDMI_PLL_REG(0x10) | ||
175 | #define PLLCTRL_CFG3 HDMI_PLL_REG(0x14) | ||
176 | #define PLLCTRL_CFG4 HDMI_PLL_REG(0x20) | ||
177 | |||
178 | /* HDMI PHY */ | ||
179 | #define HDMI_PHY_REG(idx) HDMI_REG(HDMI_PHY + idx) | ||
180 | |||
181 | #define HDMI_TXPHY_TX_CTRL HDMI_PHY_REG(0x0) | ||
182 | #define HDMI_TXPHY_DIGITAL_CTRL HDMI_PHY_REG(0x4) | ||
183 | #define HDMI_TXPHY_POWER_CTRL HDMI_PHY_REG(0x8) | ||
184 | #define HDMI_TXPHY_PAD_CFG_CTRL HDMI_PHY_REG(0xC) | ||
185 | |||
186 | /* HDMI EDID Length */ | ||
187 | #define HDMI_EDID_MAX_LENGTH 256 | ||
188 | #define EDID_TIMING_DESCRIPTOR_SIZE 0x12 | ||
189 | #define EDID_DESCRIPTOR_BLOCK0_ADDRESS 0x36 | ||
190 | #define EDID_DESCRIPTOR_BLOCK1_ADDRESS 0x80 | ||
191 | #define EDID_SIZE_BLOCK0_TIMING_DESCRIPTOR 4 | ||
192 | #define EDID_SIZE_BLOCK1_TIMING_DESCRIPTOR 4 | ||
193 | |||
194 | #define OMAP_HDMI_TIMINGS_NB 34 | ||
195 | |||
196 | #define REG_FLD_MOD(idx, val, start, end) \ | ||
197 | hdmi_write_reg(idx, FLD_MOD(hdmi_read_reg(idx), val, start, end)) | ||
198 | #define REG_GET(idx, start, end) \ | ||
199 | FLD_GET(hdmi_read_reg(idx), start, end) | ||
200 | |||
201 | /* HDMI timing structure */ | ||
202 | struct hdmi_timings { | ||
203 | struct omap_video_timings timings; | ||
204 | int vsync_pol; | ||
205 | int hsync_pol; | ||
206 | }; | ||
207 | |||
208 | enum hdmi_phy_pwr { | ||
209 | HDMI_PHYPWRCMD_OFF = 0, | ||
210 | HDMI_PHYPWRCMD_LDOON = 1, | ||
211 | HDMI_PHYPWRCMD_TXON = 2 | ||
212 | }; | ||
213 | |||
214 | enum hdmi_pll_pwr { | ||
215 | HDMI_PLLPWRCMD_ALLOFF = 0, | ||
216 | HDMI_PLLPWRCMD_PLLONLY = 1, | ||
217 | HDMI_PLLPWRCMD_BOTHON_ALLCLKS = 2, | ||
218 | HDMI_PLLPWRCMD_BOTHON_NOPHYCLK = 3 | ||
219 | }; | ||
220 | |||
221 | enum hdmi_clk_refsel { | ||
222 | HDMI_REFSEL_PCLK = 0, | ||
223 | HDMI_REFSEL_REF1 = 1, | ||
224 | HDMI_REFSEL_REF2 = 2, | ||
225 | HDMI_REFSEL_SYSCLK = 3 | ||
226 | }; | ||
227 | |||
228 | enum hdmi_core_inputbus_width { | ||
229 | HDMI_INPUT_8BIT = 0, | ||
230 | HDMI_INPUT_10BIT = 1, | ||
231 | HDMI_INPUT_12BIT = 2 | ||
232 | }; | ||
233 | |||
234 | enum hdmi_core_dither_trunc { | ||
235 | HDMI_OUTPUTTRUNCATION_8BIT = 0, | ||
236 | HDMI_OUTPUTTRUNCATION_10BIT = 1, | ||
237 | HDMI_OUTPUTTRUNCATION_12BIT = 2, | ||
238 | HDMI_OUTPUTDITHER_8BIT = 3, | ||
239 | HDMI_OUTPUTDITHER_10BIT = 4, | ||
240 | HDMI_OUTPUTDITHER_12BIT = 5 | ||
241 | }; | ||
242 | |||
243 | enum hdmi_core_deepcolor_ed { | ||
244 | HDMI_DEEPCOLORPACKECTDISABLE = 0, | ||
245 | HDMI_DEEPCOLORPACKECTENABLE = 1 | ||
246 | }; | ||
247 | |||
248 | enum hdmi_core_packet_mode { | ||
249 | HDMI_PACKETMODERESERVEDVALUE = 0, | ||
250 | HDMI_PACKETMODE24BITPERPIXEL = 4, | ||
251 | HDMI_PACKETMODE30BITPERPIXEL = 5, | ||
252 | HDMI_PACKETMODE36BITPERPIXEL = 6, | ||
253 | HDMI_PACKETMODE48BITPERPIXEL = 7 | ||
254 | }; | ||
255 | |||
256 | enum hdmi_core_hdmi_dvi { | ||
257 | HDMI_DVI = 0, | ||
258 | HDMI_HDMI = 1 | ||
259 | }; | ||
260 | |||
261 | enum hdmi_core_tclkselclkmult { | ||
262 | HDMI_FPLL05IDCK = 0, | ||
263 | HDMI_FPLL10IDCK = 1, | ||
264 | HDMI_FPLL20IDCK = 2, | ||
265 | HDMI_FPLL40IDCK = 3 | ||
266 | }; | ||
267 | |||
268 | enum hdmi_core_packet_ctrl { | ||
269 | HDMI_PACKETENABLE = 1, | ||
270 | HDMI_PACKETDISABLE = 0, | ||
271 | HDMI_PACKETREPEATON = 1, | ||
272 | HDMI_PACKETREPEATOFF = 0 | ||
273 | }; | ||
274 | |||
275 | /* INFOFRAME_AVI_ definitions */ | ||
276 | enum hdmi_core_infoframe { | ||
277 | HDMI_INFOFRAME_AVI_DB1Y_RGB = 0, | ||
278 | HDMI_INFOFRAME_AVI_DB1Y_YUV422 = 1, | ||
279 | HDMI_INFOFRAME_AVI_DB1Y_YUV444 = 2, | ||
280 | HDMI_INFOFRAME_AVI_DB1A_ACTIVE_FORMAT_OFF = 0, | ||
281 | HDMI_INFOFRAME_AVI_DB1A_ACTIVE_FORMAT_ON = 1, | ||
282 | HDMI_INFOFRAME_AVI_DB1B_NO = 0, | ||
283 | HDMI_INFOFRAME_AVI_DB1B_VERT = 1, | ||
284 | HDMI_INFOFRAME_AVI_DB1B_HORI = 2, | ||
285 | HDMI_INFOFRAME_AVI_DB1B_VERTHORI = 3, | ||
286 | HDMI_INFOFRAME_AVI_DB1S_0 = 0, | ||
287 | HDMI_INFOFRAME_AVI_DB1S_1 = 1, | ||
288 | HDMI_INFOFRAME_AVI_DB1S_2 = 2, | ||
289 | HDMI_INFOFRAME_AVI_DB2C_NO = 0, | ||
290 | HDMI_INFOFRAME_AVI_DB2C_ITU601 = 1, | ||
291 | HDMI_INFOFRAME_AVI_DB2C_ITU709 = 2, | ||
292 | HDMI_INFOFRAME_AVI_DB2C_EC_EXTENDED = 3, | ||
293 | HDMI_INFOFRAME_AVI_DB2M_NO = 0, | ||
294 | HDMI_INFOFRAME_AVI_DB2M_43 = 1, | ||
295 | HDMI_INFOFRAME_AVI_DB2M_169 = 2, | ||
296 | HDMI_INFOFRAME_AVI_DB2R_SAME = 8, | ||
297 | HDMI_INFOFRAME_AVI_DB2R_43 = 9, | ||
298 | HDMI_INFOFRAME_AVI_DB2R_169 = 10, | ||
299 | HDMI_INFOFRAME_AVI_DB2R_149 = 11, | ||
300 | HDMI_INFOFRAME_AVI_DB3ITC_NO = 0, | ||
301 | HDMI_INFOFRAME_AVI_DB3ITC_YES = 1, | ||
302 | HDMI_INFOFRAME_AVI_DB3EC_XVYUV601 = 0, | ||
303 | HDMI_INFOFRAME_AVI_DB3EC_XVYUV709 = 1, | ||
304 | HDMI_INFOFRAME_AVI_DB3Q_DEFAULT = 0, | ||
305 | HDMI_INFOFRAME_AVI_DB3Q_LR = 1, | ||
306 | HDMI_INFOFRAME_AVI_DB3Q_FR = 2, | ||
307 | HDMI_INFOFRAME_AVI_DB3SC_NO = 0, | ||
308 | HDMI_INFOFRAME_AVI_DB3SC_HORI = 1, | ||
309 | HDMI_INFOFRAME_AVI_DB3SC_VERT = 2, | ||
310 | HDMI_INFOFRAME_AVI_DB3SC_HORIVERT = 3, | ||
311 | HDMI_INFOFRAME_AVI_DB5PR_NO = 0, | ||
312 | HDMI_INFOFRAME_AVI_DB5PR_2 = 1, | ||
313 | HDMI_INFOFRAME_AVI_DB5PR_3 = 2, | ||
314 | HDMI_INFOFRAME_AVI_DB5PR_4 = 3, | ||
315 | HDMI_INFOFRAME_AVI_DB5PR_5 = 4, | ||
316 | HDMI_INFOFRAME_AVI_DB5PR_6 = 5, | ||
317 | HDMI_INFOFRAME_AVI_DB5PR_7 = 6, | ||
318 | HDMI_INFOFRAME_AVI_DB5PR_8 = 7, | ||
319 | HDMI_INFOFRAME_AVI_DB5PR_9 = 8, | ||
320 | HDMI_INFOFRAME_AVI_DB5PR_10 = 9 | ||
321 | }; | ||
322 | |||
323 | enum hdmi_packing_mode { | ||
324 | HDMI_PACK_10b_RGB_YUV444 = 0, | ||
325 | HDMI_PACK_24b_RGB_YUV444_YUV422 = 1, | ||
326 | HDMI_PACK_20b_YUV422 = 2, | ||
327 | HDMI_PACK_ALREADYPACKED = 7 | ||
328 | }; | ||
329 | |||
330 | struct hdmi_core_video_config { | ||
331 | enum hdmi_core_inputbus_width ip_bus_width; | ||
332 | enum hdmi_core_dither_trunc op_dither_truc; | ||
333 | enum hdmi_core_deepcolor_ed deep_color_pkt; | ||
334 | enum hdmi_core_packet_mode pkt_mode; | ||
335 | enum hdmi_core_hdmi_dvi hdmi_dvi; | ||
336 | enum hdmi_core_tclkselclkmult tclk_sel_clkmult; | ||
337 | }; | ||
338 | |||
339 | /* | ||
340 | * Refer to section 8.2 in HDMI 1.3 specification for | ||
341 | * details about infoframe databytes | ||
342 | */ | ||
343 | struct hdmi_core_infoframe_avi { | ||
344 | u8 db1_format; | ||
345 | /* Y0, Y1 rgb,yCbCr */ | ||
346 | u8 db1_active_info; | ||
347 | /* A0 Active information Present */ | ||
348 | u8 db1_bar_info_dv; | ||
349 | /* B0, B1 Bar info data valid */ | ||
350 | u8 db1_scan_info; | ||
351 | /* S0, S1 scan information */ | ||
352 | u8 db2_colorimetry; | ||
353 | /* C0, C1 colorimetry */ | ||
354 | u8 db2_aspect_ratio; | ||
355 | /* M0, M1 Aspect ratio (4:3, 16:9) */ | ||
356 | u8 db2_active_fmt_ar; | ||
357 | /* R0...R3 Active format aspect ratio */ | ||
358 | u8 db3_itc; | ||
359 | /* ITC IT content. */ | ||
360 | u8 db3_ec; | ||
361 | /* EC0, EC1, EC2 Extended colorimetry */ | ||
362 | u8 db3_q_range; | ||
363 | /* Q1, Q0 Quantization range */ | ||
364 | u8 db3_nup_scaling; | ||
365 | /* SC1, SC0 Non-uniform picture scaling */ | ||
366 | u8 db4_videocode; | ||
367 | /* VIC0..6 Video format identification */ | ||
368 | u8 db5_pixel_repeat; | ||
369 | /* PR0..PR3 Pixel repetition factor */ | ||
370 | u16 db6_7_line_eoftop; | ||
371 | /* Line number end of top bar */ | ||
372 | u16 db8_9_line_sofbottom; | ||
373 | /* Line number start of bottom bar */ | ||
374 | u16 db10_11_pixel_eofleft; | ||
375 | /* Pixel number end of left bar */ | ||
376 | u16 db12_13_pixel_sofright; | ||
377 | /* Pixel number start of right bar */ | ||
378 | }; | ||
379 | |||
380 | struct hdmi_core_packet_enable_repeat { | ||
381 | u32 audio_pkt; | ||
382 | u32 audio_pkt_repeat; | ||
383 | u32 avi_infoframe; | ||
384 | u32 avi_infoframe_repeat; | ||
385 | u32 gen_cntrl_pkt; | ||
386 | u32 gen_cntrl_pkt_repeat; | ||
387 | u32 generic_pkt; | ||
388 | u32 generic_pkt_repeat; | ||
389 | }; | ||
390 | |||
391 | struct hdmi_video_format { | ||
392 | enum hdmi_packing_mode packing_mode; | ||
393 | u32 y_res; /* Line per panel */ | ||
394 | u32 x_res; /* pixel per line */ | ||
395 | }; | ||
396 | |||
397 | struct hdmi_video_interface { | ||
398 | int vsp; /* Vsync polarity */ | ||
399 | int hsp; /* Hsync polarity */ | ||
400 | int interlacing; | ||
401 | int tm; /* Timing mode */ | ||
402 | }; | ||
403 | |||
404 | struct hdmi_cm { | ||
405 | int code; | ||
406 | int mode; | ||
407 | }; | ||
408 | |||
409 | struct hdmi_config { | ||
410 | struct hdmi_timings timings; | ||
411 | u16 interlace; | ||
412 | struct hdmi_cm cm; | ||
413 | }; | ||
414 | |||
415 | #endif | ||
diff --git a/drivers/video/omap2/dss/hdmi_omap4_panel.c b/drivers/video/omap2/dss/hdmi_omap4_panel.c new file mode 100644 index 000000000000..ffb5de94131f --- /dev/null +++ b/drivers/video/omap2/dss/hdmi_omap4_panel.c | |||
@@ -0,0 +1,222 @@ | |||
1 | /* | ||
2 | * hdmi_omap4_panel.c | ||
3 | * | ||
4 | * HDMI library support functions for TI OMAP4 processors. | ||
5 | * | ||
6 | * Copyright (C) 2010-2011 Texas Instruments Incorporated - http://www.ti.com/ | ||
7 | * Authors: Mythri P k <mythripk@ti.com> | ||
8 | * | ||
9 | * This program is free software; you can redistribute it and/or modify it | ||
10 | * under the terms of the GNU General Public License version 2 as published by | ||
11 | * the Free Software Foundation. | ||
12 | * | ||
13 | * This program is distributed in the hope that it will be useful, but WITHOUT | ||
14 | * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or | ||
15 | * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for | ||
16 | * more details. | ||
17 | * | ||
18 | * You should have received a copy of the GNU General Public License along with | ||
19 | * this program. If not, see <http://www.gnu.org/licenses/>. | ||
20 | */ | ||
21 | |||
22 | #include <linux/kernel.h> | ||
23 | #include <linux/err.h> | ||
24 | #include <linux/io.h> | ||
25 | #include <linux/mutex.h> | ||
26 | #include <linux/module.h> | ||
27 | #include <plat/display.h> | ||
28 | |||
29 | #include "dss.h" | ||
30 | |||
31 | static struct { | ||
32 | struct mutex hdmi_lock; | ||
33 | } hdmi; | ||
34 | |||
35 | |||
36 | static int hdmi_panel_probe(struct omap_dss_device *dssdev) | ||
37 | { | ||
38 | DSSDBG("ENTER hdmi_panel_probe\n"); | ||
39 | |||
40 | dssdev->panel.config = OMAP_DSS_LCD_TFT | | ||
41 | OMAP_DSS_LCD_IVS | OMAP_DSS_LCD_IHS; | ||
42 | |||
43 | /* | ||
44 | * Initialize the timings to 640 * 480 | ||
45 | * This is only for framebuffer update not for TV timing setting | ||
46 | * Setting TV timing will be done only on enable | ||
47 | */ | ||
48 | dssdev->panel.timings.x_res = 640; | ||
49 | dssdev->panel.timings.y_res = 480; | ||
50 | |||
51 | DSSDBG("hdmi_panel_probe x_res= %d y_res = %d\n", | ||
52 | dssdev->panel.timings.x_res, | ||
53 | dssdev->panel.timings.y_res); | ||
54 | return 0; | ||
55 | } | ||
56 | |||
57 | static void hdmi_panel_remove(struct omap_dss_device *dssdev) | ||
58 | { | ||
59 | |||
60 | } | ||
61 | |||
62 | static int hdmi_panel_enable(struct omap_dss_device *dssdev) | ||
63 | { | ||
64 | int r = 0; | ||
65 | DSSDBG("ENTER hdmi_panel_enable\n"); | ||
66 | |||
67 | mutex_lock(&hdmi.hdmi_lock); | ||
68 | |||
69 | if (dssdev->state != OMAP_DSS_DISPLAY_DISABLED) { | ||
70 | r = -EINVAL; | ||
71 | goto err; | ||
72 | } | ||
73 | |||
74 | r = omapdss_hdmi_display_enable(dssdev); | ||
75 | if (r) { | ||
76 | DSSERR("failed to power on\n"); | ||
77 | goto err; | ||
78 | } | ||
79 | |||
80 | dssdev->state = OMAP_DSS_DISPLAY_ACTIVE; | ||
81 | |||
82 | err: | ||
83 | mutex_unlock(&hdmi.hdmi_lock); | ||
84 | |||
85 | return r; | ||
86 | } | ||
87 | |||
88 | static void hdmi_panel_disable(struct omap_dss_device *dssdev) | ||
89 | { | ||
90 | mutex_lock(&hdmi.hdmi_lock); | ||
91 | |||
92 | if (dssdev->state == OMAP_DSS_DISPLAY_ACTIVE) | ||
93 | omapdss_hdmi_display_disable(dssdev); | ||
94 | |||
95 | dssdev->state = OMAP_DSS_DISPLAY_DISABLED; | ||
96 | |||
97 | mutex_unlock(&hdmi.hdmi_lock); | ||
98 | } | ||
99 | |||
100 | static int hdmi_panel_suspend(struct omap_dss_device *dssdev) | ||
101 | { | ||
102 | int r = 0; | ||
103 | |||
104 | mutex_lock(&hdmi.hdmi_lock); | ||
105 | |||
106 | if (dssdev->state != OMAP_DSS_DISPLAY_ACTIVE) { | ||
107 | r = -EINVAL; | ||
108 | goto err; | ||
109 | } | ||
110 | |||
111 | dssdev->state = OMAP_DSS_DISPLAY_SUSPENDED; | ||
112 | |||
113 | omapdss_hdmi_display_disable(dssdev); | ||
114 | |||
115 | err: | ||
116 | mutex_unlock(&hdmi.hdmi_lock); | ||
117 | |||
118 | return r; | ||
119 | } | ||
120 | |||
121 | static int hdmi_panel_resume(struct omap_dss_device *dssdev) | ||
122 | { | ||
123 | int r = 0; | ||
124 | |||
125 | mutex_lock(&hdmi.hdmi_lock); | ||
126 | |||
127 | if (dssdev->state != OMAP_DSS_DISPLAY_SUSPENDED) { | ||
128 | r = -EINVAL; | ||
129 | goto err; | ||
130 | } | ||
131 | |||
132 | r = omapdss_hdmi_display_enable(dssdev); | ||
133 | if (r) { | ||
134 | DSSERR("failed to power on\n"); | ||
135 | goto err; | ||
136 | } | ||
137 | |||
138 | dssdev->state = OMAP_DSS_DISPLAY_ACTIVE; | ||
139 | |||
140 | err: | ||
141 | mutex_unlock(&hdmi.hdmi_lock); | ||
142 | |||
143 | return r; | ||
144 | } | ||
145 | |||
146 | static void hdmi_get_timings(struct omap_dss_device *dssdev, | ||
147 | struct omap_video_timings *timings) | ||
148 | { | ||
149 | mutex_lock(&hdmi.hdmi_lock); | ||
150 | |||
151 | *timings = dssdev->panel.timings; | ||
152 | |||
153 | mutex_unlock(&hdmi.hdmi_lock); | ||
154 | } | ||
155 | |||
156 | static void hdmi_set_timings(struct omap_dss_device *dssdev, | ||
157 | struct omap_video_timings *timings) | ||
158 | { | ||
159 | DSSDBG("hdmi_set_timings\n"); | ||
160 | |||
161 | mutex_lock(&hdmi.hdmi_lock); | ||
162 | |||
163 | dssdev->panel.timings = *timings; | ||
164 | |||
165 | if (dssdev->state == OMAP_DSS_DISPLAY_ACTIVE) { | ||
166 | /* turn the hdmi off and on to get new timings to use */ | ||
167 | omapdss_hdmi_display_disable(dssdev); | ||
168 | omapdss_hdmi_display_set_timing(dssdev); | ||
169 | } | ||
170 | |||
171 | mutex_unlock(&hdmi.hdmi_lock); | ||
172 | } | ||
173 | |||
174 | static int hdmi_check_timings(struct omap_dss_device *dssdev, | ||
175 | struct omap_video_timings *timings) | ||
176 | { | ||
177 | int r = 0; | ||
178 | |||
179 | DSSDBG("hdmi_check_timings\n"); | ||
180 | |||
181 | mutex_lock(&hdmi.hdmi_lock); | ||
182 | |||
183 | r = omapdss_hdmi_display_check_timing(dssdev, timings); | ||
184 | if (r) { | ||
185 | DSSERR("Timing cannot be applied\n"); | ||
186 | goto err; | ||
187 | } | ||
188 | err: | ||
189 | mutex_unlock(&hdmi.hdmi_lock); | ||
190 | return r; | ||
191 | } | ||
192 | |||
193 | static struct omap_dss_driver hdmi_driver = { | ||
194 | .probe = hdmi_panel_probe, | ||
195 | .remove = hdmi_panel_remove, | ||
196 | .enable = hdmi_panel_enable, | ||
197 | .disable = hdmi_panel_disable, | ||
198 | .suspend = hdmi_panel_suspend, | ||
199 | .resume = hdmi_panel_resume, | ||
200 | .get_timings = hdmi_get_timings, | ||
201 | .set_timings = hdmi_set_timings, | ||
202 | .check_timings = hdmi_check_timings, | ||
203 | .driver = { | ||
204 | .name = "hdmi_panel", | ||
205 | .owner = THIS_MODULE, | ||
206 | }, | ||
207 | }; | ||
208 | |||
209 | int hdmi_panel_init(void) | ||
210 | { | ||
211 | mutex_init(&hdmi.hdmi_lock); | ||
212 | |||
213 | omap_dss_register_driver(&hdmi_driver); | ||
214 | |||
215 | return 0; | ||
216 | } | ||
217 | |||
218 | void hdmi_panel_exit(void) | ||
219 | { | ||
220 | omap_dss_unregister_driver(&hdmi_driver); | ||
221 | |||
222 | } | ||
diff --git a/drivers/video/omap2/dss/manager.c b/drivers/video/omap2/dss/manager.c index 172d4e697309..bcd37ec86952 100644 --- a/drivers/video/omap2/dss/manager.c +++ b/drivers/video/omap2/dss/manager.c | |||
@@ -515,6 +515,8 @@ static int dss_mgr_wait_for_vsync(struct omap_overlay_manager *mgr) | |||
515 | 515 | ||
516 | if (mgr->device->type == OMAP_DISPLAY_TYPE_VENC) { | 516 | if (mgr->device->type == OMAP_DISPLAY_TYPE_VENC) { |
517 | irq = DISPC_IRQ_EVSYNC_ODD; | 517 | irq = DISPC_IRQ_EVSYNC_ODD; |
518 | } else if (mgr->device->type == OMAP_DISPLAY_TYPE_HDMI) { | ||
519 | irq = DISPC_IRQ_EVSYNC_EVEN; | ||
518 | } else { | 520 | } else { |
519 | if (mgr->id == OMAP_DSS_CHANNEL_LCD) | 521 | if (mgr->id == OMAP_DSS_CHANNEL_LCD) |
520 | irq = DISPC_IRQ_VSYNC; | 522 | irq = DISPC_IRQ_VSYNC; |
@@ -536,7 +538,8 @@ static int dss_mgr_wait_for_go(struct omap_overlay_manager *mgr) | |||
536 | if (!dssdev || dssdev->state != OMAP_DSS_DISPLAY_ACTIVE) | 538 | if (!dssdev || dssdev->state != OMAP_DSS_DISPLAY_ACTIVE) |
537 | return 0; | 539 | return 0; |
538 | 540 | ||
539 | if (dssdev->type == OMAP_DISPLAY_TYPE_VENC) { | 541 | if (dssdev->type == OMAP_DISPLAY_TYPE_VENC |
542 | || dssdev->type == OMAP_DISPLAY_TYPE_HDMI) { | ||
540 | irq = DISPC_IRQ_EVSYNC_ODD | DISPC_IRQ_EVSYNC_EVEN; | 543 | irq = DISPC_IRQ_EVSYNC_ODD | DISPC_IRQ_EVSYNC_EVEN; |
541 | } else { | 544 | } else { |
542 | if (dssdev->caps & OMAP_DSS_DISPLAY_CAP_MANUAL_UPDATE) { | 545 | if (dssdev->caps & OMAP_DSS_DISPLAY_CAP_MANUAL_UPDATE) { |
@@ -613,7 +616,8 @@ int dss_mgr_wait_for_go_ovl(struct omap_overlay *ovl) | |||
613 | if (!dssdev || dssdev->state != OMAP_DSS_DISPLAY_ACTIVE) | 616 | if (!dssdev || dssdev->state != OMAP_DSS_DISPLAY_ACTIVE) |
614 | return 0; | 617 | return 0; |
615 | 618 | ||
616 | if (dssdev->type == OMAP_DISPLAY_TYPE_VENC) { | 619 | if (dssdev->type == OMAP_DISPLAY_TYPE_VENC |
620 | || dssdev->type == OMAP_DISPLAY_TYPE_HDMI) { | ||
617 | irq = DISPC_IRQ_EVSYNC_ODD | DISPC_IRQ_EVSYNC_EVEN; | 621 | irq = DISPC_IRQ_EVSYNC_ODD | DISPC_IRQ_EVSYNC_EVEN; |
618 | } else { | 622 | } else { |
619 | if (dssdev->caps & OMAP_DSS_DISPLAY_CAP_MANUAL_UPDATE) { | 623 | if (dssdev->caps & OMAP_DSS_DISPLAY_CAP_MANUAL_UPDATE) { |
@@ -1377,6 +1381,7 @@ static int omap_dss_mgr_apply(struct omap_overlay_manager *mgr) | |||
1377 | case OMAP_DISPLAY_TYPE_DBI: | 1381 | case OMAP_DISPLAY_TYPE_DBI: |
1378 | case OMAP_DISPLAY_TYPE_SDI: | 1382 | case OMAP_DISPLAY_TYPE_SDI: |
1379 | case OMAP_DISPLAY_TYPE_VENC: | 1383 | case OMAP_DISPLAY_TYPE_VENC: |
1384 | case OMAP_DISPLAY_TYPE_HDMI: | ||
1380 | default_get_overlay_fifo_thresholds(ovl->id, size, | 1385 | default_get_overlay_fifo_thresholds(ovl->id, size, |
1381 | &oc->burst_size, &oc->fifo_low, | 1386 | &oc->burst_size, &oc->fifo_low, |
1382 | &oc->fifo_high); | 1387 | &oc->fifo_high); |
@@ -1394,7 +1399,7 @@ static int omap_dss_mgr_apply(struct omap_overlay_manager *mgr) | |||
1394 | } | 1399 | } |
1395 | 1400 | ||
1396 | r = 0; | 1401 | r = 0; |
1397 | dss_clk_enable(DSS_CLK_ICK | DSS_CLK_FCK1); | 1402 | dss_clk_enable(DSS_CLK_ICK | DSS_CLK_FCK); |
1398 | if (!dss_cache.irq_enabled) { | 1403 | if (!dss_cache.irq_enabled) { |
1399 | u32 mask; | 1404 | u32 mask; |
1400 | 1405 | ||
@@ -1407,7 +1412,7 @@ static int omap_dss_mgr_apply(struct omap_overlay_manager *mgr) | |||
1407 | dss_cache.irq_enabled = true; | 1412 | dss_cache.irq_enabled = true; |
1408 | } | 1413 | } |
1409 | configure_dispc(); | 1414 | configure_dispc(); |
1410 | dss_clk_disable(DSS_CLK_ICK | DSS_CLK_FCK1); | 1415 | dss_clk_disable(DSS_CLK_ICK | DSS_CLK_FCK); |
1411 | 1416 | ||
1412 | spin_unlock_irqrestore(&dss_cache.lock, flags); | 1417 | spin_unlock_irqrestore(&dss_cache.lock, flags); |
1413 | 1418 | ||
diff --git a/drivers/video/omap2/dss/overlay.c b/drivers/video/omap2/dss/overlay.c index 456efef03c20..f1aca6d04011 100644 --- a/drivers/video/omap2/dss/overlay.c +++ b/drivers/video/omap2/dss/overlay.c | |||
@@ -490,7 +490,7 @@ static int omap_dss_set_manager(struct omap_overlay *ovl, | |||
490 | 490 | ||
491 | ovl->manager = mgr; | 491 | ovl->manager = mgr; |
492 | 492 | ||
493 | dss_clk_enable(DSS_CLK_ICK | DSS_CLK_FCK1); | 493 | dss_clk_enable(DSS_CLK_ICK | DSS_CLK_FCK); |
494 | /* XXX: on manual update display, in auto update mode, a bug happens | 494 | /* XXX: on manual update display, in auto update mode, a bug happens |
495 | * here. When an overlay is first enabled on LCD, then it's disabled, | 495 | * here. When an overlay is first enabled on LCD, then it's disabled, |
496 | * and the manager is changed to TV, we sometimes get SYNC_LOST_DIGIT | 496 | * and the manager is changed to TV, we sometimes get SYNC_LOST_DIGIT |
@@ -499,7 +499,7 @@ static int omap_dss_set_manager(struct omap_overlay *ovl, | |||
499 | * but I don't understand how or why. */ | 499 | * but I don't understand how or why. */ |
500 | msleep(40); | 500 | msleep(40); |
501 | dispc_set_channel_out(ovl->id, mgr->id); | 501 | dispc_set_channel_out(ovl->id, mgr->id); |
502 | dss_clk_disable(DSS_CLK_ICK | DSS_CLK_FCK1); | 502 | dss_clk_disable(DSS_CLK_ICK | DSS_CLK_FCK); |
503 | 503 | ||
504 | return 0; | 504 | return 0; |
505 | } | 505 | } |
@@ -679,7 +679,8 @@ void dss_recheck_connections(struct omap_dss_device *dssdev, bool force) | |||
679 | lcd2_mgr->set_device(lcd2_mgr, dssdev); | 679 | lcd2_mgr->set_device(lcd2_mgr, dssdev); |
680 | mgr = lcd2_mgr; | 680 | mgr = lcd2_mgr; |
681 | } | 681 | } |
682 | } else if (dssdev->type != OMAP_DISPLAY_TYPE_VENC) { | 682 | } else if (dssdev->type != OMAP_DISPLAY_TYPE_VENC |
683 | && dssdev->type != OMAP_DISPLAY_TYPE_HDMI) { | ||
683 | if (!lcd_mgr->device || force) { | 684 | if (!lcd_mgr->device || force) { |
684 | if (lcd_mgr->device) | 685 | if (lcd_mgr->device) |
685 | lcd_mgr->unset_device(lcd_mgr); | 686 | lcd_mgr->unset_device(lcd_mgr); |
@@ -688,7 +689,8 @@ void dss_recheck_connections(struct omap_dss_device *dssdev, bool force) | |||
688 | } | 689 | } |
689 | } | 690 | } |
690 | 691 | ||
691 | if (dssdev->type == OMAP_DISPLAY_TYPE_VENC) { | 692 | if (dssdev->type == OMAP_DISPLAY_TYPE_VENC |
693 | || dssdev->type == OMAP_DISPLAY_TYPE_HDMI) { | ||
692 | if (!tv_mgr->device || force) { | 694 | if (!tv_mgr->device || force) { |
693 | if (tv_mgr->device) | 695 | if (tv_mgr->device) |
694 | tv_mgr->unset_device(tv_mgr); | 696 | tv_mgr->unset_device(tv_mgr); |
diff --git a/drivers/video/omap2/dss/rfbi.c b/drivers/video/omap2/dss/rfbi.c index 10a2ffe02882..5ea17f49c611 100644 --- a/drivers/video/omap2/dss/rfbi.c +++ b/drivers/video/omap2/dss/rfbi.c | |||
@@ -36,8 +36,6 @@ | |||
36 | #include <plat/display.h> | 36 | #include <plat/display.h> |
37 | #include "dss.h" | 37 | #include "dss.h" |
38 | 38 | ||
39 | #define RFBI_BASE 0x48050800 | ||
40 | |||
41 | struct rfbi_reg { u16 idx; }; | 39 | struct rfbi_reg { u16 idx; }; |
42 | 40 | ||
43 | #define RFBI_REG(idx) ((const struct rfbi_reg) { idx }) | 41 | #define RFBI_REG(idx) ((const struct rfbi_reg) { idx }) |
@@ -100,6 +98,7 @@ static int rfbi_convert_timings(struct rfbi_timings *t); | |||
100 | static void rfbi_get_clk_info(u32 *clk_period, u32 *max_clk_div); | 98 | static void rfbi_get_clk_info(u32 *clk_period, u32 *max_clk_div); |
101 | 99 | ||
102 | static struct { | 100 | static struct { |
101 | struct platform_device *pdev; | ||
103 | void __iomem *base; | 102 | void __iomem *base; |
104 | 103 | ||
105 | unsigned long l4_khz; | 104 | unsigned long l4_khz; |
@@ -142,9 +141,9 @@ static inline u32 rfbi_read_reg(const struct rfbi_reg idx) | |||
142 | static void rfbi_enable_clocks(bool enable) | 141 | static void rfbi_enable_clocks(bool enable) |
143 | { | 142 | { |
144 | if (enable) | 143 | if (enable) |
145 | dss_clk_enable(DSS_CLK_ICK | DSS_CLK_FCK1); | 144 | dss_clk_enable(DSS_CLK_ICK | DSS_CLK_FCK); |
146 | else | 145 | else |
147 | dss_clk_disable(DSS_CLK_ICK | DSS_CLK_FCK1); | 146 | dss_clk_disable(DSS_CLK_ICK | DSS_CLK_FCK); |
148 | } | 147 | } |
149 | 148 | ||
150 | void omap_rfbi_write_command(const void *buf, u32 len) | 149 | void omap_rfbi_write_command(const void *buf, u32 len) |
@@ -497,7 +496,7 @@ unsigned long rfbi_get_max_tx_rate(void) | |||
497 | }; | 496 | }; |
498 | 497 | ||
499 | l4_rate = rfbi.l4_khz / 1000; | 498 | l4_rate = rfbi.l4_khz / 1000; |
500 | dss1_rate = dss_clk_get_rate(DSS_CLK_FCK1) / 1000000; | 499 | dss1_rate = dss_clk_get_rate(DSS_CLK_FCK) / 1000000; |
501 | 500 | ||
502 | for (i = 0; i < ARRAY_SIZE(ftab); i++) { | 501 | for (i = 0; i < ARRAY_SIZE(ftab); i++) { |
503 | /* Use a window instead of an exact match, to account | 502 | /* Use a window instead of an exact match, to account |
@@ -922,7 +921,7 @@ void rfbi_dump_regs(struct seq_file *s) | |||
922 | { | 921 | { |
923 | #define DUMPREG(r) seq_printf(s, "%-35s %08x\n", #r, rfbi_read_reg(r)) | 922 | #define DUMPREG(r) seq_printf(s, "%-35s %08x\n", #r, rfbi_read_reg(r)) |
924 | 923 | ||
925 | dss_clk_enable(DSS_CLK_ICK | DSS_CLK_FCK1); | 924 | dss_clk_enable(DSS_CLK_ICK | DSS_CLK_FCK); |
926 | 925 | ||
927 | DUMPREG(RFBI_REVISION); | 926 | DUMPREG(RFBI_REVISION); |
928 | DUMPREG(RFBI_SYSCONFIG); | 927 | DUMPREG(RFBI_SYSCONFIG); |
@@ -953,54 +952,10 @@ void rfbi_dump_regs(struct seq_file *s) | |||
953 | DUMPREG(RFBI_VSYNC_WIDTH); | 952 | DUMPREG(RFBI_VSYNC_WIDTH); |
954 | DUMPREG(RFBI_HSYNC_WIDTH); | 953 | DUMPREG(RFBI_HSYNC_WIDTH); |
955 | 954 | ||
956 | dss_clk_disable(DSS_CLK_ICK | DSS_CLK_FCK1); | 955 | dss_clk_disable(DSS_CLK_ICK | DSS_CLK_FCK); |
957 | #undef DUMPREG | 956 | #undef DUMPREG |
958 | } | 957 | } |
959 | 958 | ||
960 | int rfbi_init(void) | ||
961 | { | ||
962 | u32 rev; | ||
963 | u32 l; | ||
964 | |||
965 | spin_lock_init(&rfbi.cmd_lock); | ||
966 | |||
967 | init_completion(&rfbi.cmd_done); | ||
968 | atomic_set(&rfbi.cmd_fifo_full, 0); | ||
969 | atomic_set(&rfbi.cmd_pending, 0); | ||
970 | |||
971 | rfbi.base = ioremap(RFBI_BASE, SZ_256); | ||
972 | if (!rfbi.base) { | ||
973 | DSSERR("can't ioremap RFBI\n"); | ||
974 | return -ENOMEM; | ||
975 | } | ||
976 | |||
977 | rfbi_enable_clocks(1); | ||
978 | |||
979 | msleep(10); | ||
980 | |||
981 | rfbi.l4_khz = dss_clk_get_rate(DSS_CLK_ICK) / 1000; | ||
982 | |||
983 | /* Enable autoidle and smart-idle */ | ||
984 | l = rfbi_read_reg(RFBI_SYSCONFIG); | ||
985 | l |= (1 << 0) | (2 << 3); | ||
986 | rfbi_write_reg(RFBI_SYSCONFIG, l); | ||
987 | |||
988 | rev = rfbi_read_reg(RFBI_REVISION); | ||
989 | printk(KERN_INFO "OMAP RFBI rev %d.%d\n", | ||
990 | FLD_GET(rev, 7, 4), FLD_GET(rev, 3, 0)); | ||
991 | |||
992 | rfbi_enable_clocks(0); | ||
993 | |||
994 | return 0; | ||
995 | } | ||
996 | |||
997 | void rfbi_exit(void) | ||
998 | { | ||
999 | DSSDBG("rfbi_exit\n"); | ||
1000 | |||
1001 | iounmap(rfbi.base); | ||
1002 | } | ||
1003 | |||
1004 | int omapdss_rfbi_display_enable(struct omap_dss_device *dssdev) | 959 | int omapdss_rfbi_display_enable(struct omap_dss_device *dssdev) |
1005 | { | 960 | { |
1006 | int r; | 961 | int r; |
@@ -1056,3 +1011,74 @@ int rfbi_init_display(struct omap_dss_device *dssdev) | |||
1056 | dssdev->caps = OMAP_DSS_DISPLAY_CAP_MANUAL_UPDATE; | 1011 | dssdev->caps = OMAP_DSS_DISPLAY_CAP_MANUAL_UPDATE; |
1057 | return 0; | 1012 | return 0; |
1058 | } | 1013 | } |
1014 | |||
1015 | /* RFBI HW IP initialisation */ | ||
1016 | static int omap_rfbihw_probe(struct platform_device *pdev) | ||
1017 | { | ||
1018 | u32 rev; | ||
1019 | u32 l; | ||
1020 | struct resource *rfbi_mem; | ||
1021 | |||
1022 | rfbi.pdev = pdev; | ||
1023 | |||
1024 | spin_lock_init(&rfbi.cmd_lock); | ||
1025 | |||
1026 | init_completion(&rfbi.cmd_done); | ||
1027 | atomic_set(&rfbi.cmd_fifo_full, 0); | ||
1028 | atomic_set(&rfbi.cmd_pending, 0); | ||
1029 | |||
1030 | rfbi_mem = platform_get_resource(rfbi.pdev, IORESOURCE_MEM, 0); | ||
1031 | if (!rfbi_mem) { | ||
1032 | DSSERR("can't get IORESOURCE_MEM RFBI\n"); | ||
1033 | return -EINVAL; | ||
1034 | } | ||
1035 | rfbi.base = ioremap(rfbi_mem->start, resource_size(rfbi_mem)); | ||
1036 | if (!rfbi.base) { | ||
1037 | DSSERR("can't ioremap RFBI\n"); | ||
1038 | return -ENOMEM; | ||
1039 | } | ||
1040 | |||
1041 | rfbi_enable_clocks(1); | ||
1042 | |||
1043 | msleep(10); | ||
1044 | |||
1045 | rfbi.l4_khz = dss_clk_get_rate(DSS_CLK_ICK) / 1000; | ||
1046 | |||
1047 | /* Enable autoidle and smart-idle */ | ||
1048 | l = rfbi_read_reg(RFBI_SYSCONFIG); | ||
1049 | l |= (1 << 0) | (2 << 3); | ||
1050 | rfbi_write_reg(RFBI_SYSCONFIG, l); | ||
1051 | |||
1052 | rev = rfbi_read_reg(RFBI_REVISION); | ||
1053 | dev_dbg(&pdev->dev, "OMAP RFBI rev %d.%d\n", | ||
1054 | FLD_GET(rev, 7, 4), FLD_GET(rev, 3, 0)); | ||
1055 | |||
1056 | rfbi_enable_clocks(0); | ||
1057 | |||
1058 | return 0; | ||
1059 | } | ||
1060 | |||
1061 | static int omap_rfbihw_remove(struct platform_device *pdev) | ||
1062 | { | ||
1063 | iounmap(rfbi.base); | ||
1064 | return 0; | ||
1065 | } | ||
1066 | |||
1067 | static struct platform_driver omap_rfbihw_driver = { | ||
1068 | .probe = omap_rfbihw_probe, | ||
1069 | .remove = omap_rfbihw_remove, | ||
1070 | .driver = { | ||
1071 | .name = "omapdss_rfbi", | ||
1072 | .owner = THIS_MODULE, | ||
1073 | }, | ||
1074 | }; | ||
1075 | |||
1076 | int rfbi_init_platform_driver(void) | ||
1077 | { | ||
1078 | return platform_driver_register(&omap_rfbihw_driver); | ||
1079 | } | ||
1080 | |||
1081 | void rfbi_uninit_platform_driver(void) | ||
1082 | { | ||
1083 | return platform_driver_unregister(&omap_rfbihw_driver); | ||
1084 | } | ||
diff --git a/drivers/video/omap2/dss/sdi.c b/drivers/video/omap2/dss/sdi.c index b64adf7dfc88..54a53e648180 100644 --- a/drivers/video/omap2/dss/sdi.c +++ b/drivers/video/omap2/dss/sdi.c | |||
@@ -30,7 +30,6 @@ | |||
30 | #include "dss.h" | 30 | #include "dss.h" |
31 | 31 | ||
32 | static struct { | 32 | static struct { |
33 | bool skip_init; | ||
34 | bool update_enabled; | 33 | bool update_enabled; |
35 | struct regulator *vdds_sdi_reg; | 34 | struct regulator *vdds_sdi_reg; |
36 | } sdi; | 35 | } sdi; |
@@ -68,9 +67,7 @@ int omapdss_sdi_display_enable(struct omap_dss_device *dssdev) | |||
68 | if (r) | 67 | if (r) |
69 | goto err1; | 68 | goto err1; |
70 | 69 | ||
71 | /* In case of skip_init sdi_init has already enabled the clocks */ | 70 | dss_clk_enable(DSS_CLK_ICK | DSS_CLK_FCK); |
72 | if (!sdi.skip_init) | ||
73 | dss_clk_enable(DSS_CLK_ICK | DSS_CLK_FCK1); | ||
74 | 71 | ||
75 | sdi_basic_init(dssdev); | 72 | sdi_basic_init(dssdev); |
76 | 73 | ||
@@ -80,14 +77,8 @@ int omapdss_sdi_display_enable(struct omap_dss_device *dssdev) | |||
80 | dispc_set_pol_freq(dssdev->manager->id, dssdev->panel.config, | 77 | dispc_set_pol_freq(dssdev->manager->id, dssdev->panel.config, |
81 | dssdev->panel.acbi, dssdev->panel.acb); | 78 | dssdev->panel.acbi, dssdev->panel.acb); |
82 | 79 | ||
83 | if (!sdi.skip_init) { | 80 | r = dss_calc_clock_div(1, t->pixel_clock * 1000, |
84 | r = dss_calc_clock_div(1, t->pixel_clock * 1000, | 81 | &dss_cinfo, &dispc_cinfo); |
85 | &dss_cinfo, &dispc_cinfo); | ||
86 | } else { | ||
87 | r = dss_get_clock_div(&dss_cinfo); | ||
88 | r = dispc_get_clock_div(dssdev->manager->id, &dispc_cinfo); | ||
89 | } | ||
90 | |||
91 | if (r) | 82 | if (r) |
92 | goto err2; | 83 | goto err2; |
93 | 84 | ||
@@ -116,21 +107,17 @@ int omapdss_sdi_display_enable(struct omap_dss_device *dssdev) | |||
116 | if (r) | 107 | if (r) |
117 | goto err2; | 108 | goto err2; |
118 | 109 | ||
119 | if (!sdi.skip_init) { | 110 | dss_sdi_init(dssdev->phy.sdi.datapairs); |
120 | dss_sdi_init(dssdev->phy.sdi.datapairs); | 111 | r = dss_sdi_enable(); |
121 | r = dss_sdi_enable(); | 112 | if (r) |
122 | if (r) | 113 | goto err1; |
123 | goto err1; | 114 | mdelay(2); |
124 | mdelay(2); | ||
125 | } | ||
126 | 115 | ||
127 | dssdev->manager->enable(dssdev->manager); | 116 | dssdev->manager->enable(dssdev->manager); |
128 | 117 | ||
129 | sdi.skip_init = 0; | ||
130 | |||
131 | return 0; | 118 | return 0; |
132 | err2: | 119 | err2: |
133 | dss_clk_disable(DSS_CLK_ICK | DSS_CLK_FCK1); | 120 | dss_clk_disable(DSS_CLK_ICK | DSS_CLK_FCK); |
134 | regulator_disable(sdi.vdds_sdi_reg); | 121 | regulator_disable(sdi.vdds_sdi_reg); |
135 | err1: | 122 | err1: |
136 | omap_dss_stop_device(dssdev); | 123 | omap_dss_stop_device(dssdev); |
@@ -145,7 +132,7 @@ void omapdss_sdi_display_disable(struct omap_dss_device *dssdev) | |||
145 | 132 | ||
146 | dss_sdi_disable(); | 133 | dss_sdi_disable(); |
147 | 134 | ||
148 | dss_clk_disable(DSS_CLK_ICK | DSS_CLK_FCK1); | 135 | dss_clk_disable(DSS_CLK_ICK | DSS_CLK_FCK); |
149 | 136 | ||
150 | regulator_disable(sdi.vdds_sdi_reg); | 137 | regulator_disable(sdi.vdds_sdi_reg); |
151 | 138 | ||
@@ -157,25 +144,24 @@ int sdi_init_display(struct omap_dss_device *dssdev) | |||
157 | { | 144 | { |
158 | DSSDBG("SDI init\n"); | 145 | DSSDBG("SDI init\n"); |
159 | 146 | ||
147 | if (sdi.vdds_sdi_reg == NULL) { | ||
148 | struct regulator *vdds_sdi; | ||
149 | |||
150 | vdds_sdi = dss_get_vdds_sdi(); | ||
151 | |||
152 | if (IS_ERR(vdds_sdi)) { | ||
153 | DSSERR("can't get VDDS_SDI regulator\n"); | ||
154 | return PTR_ERR(vdds_sdi); | ||
155 | } | ||
156 | |||
157 | sdi.vdds_sdi_reg = vdds_sdi; | ||
158 | } | ||
159 | |||
160 | return 0; | 160 | return 0; |
161 | } | 161 | } |
162 | 162 | ||
163 | int sdi_init(bool skip_init) | 163 | int sdi_init(void) |
164 | { | 164 | { |
165 | /* we store this for first display enable, then clear it */ | ||
166 | sdi.skip_init = skip_init; | ||
167 | |||
168 | sdi.vdds_sdi_reg = dss_get_vdds_sdi(); | ||
169 | if (IS_ERR(sdi.vdds_sdi_reg)) { | ||
170 | DSSERR("can't get VDDS_SDI regulator\n"); | ||
171 | return PTR_ERR(sdi.vdds_sdi_reg); | ||
172 | } | ||
173 | /* | ||
174 | * Enable clocks already here, otherwise there would be a toggle | ||
175 | * of them until sdi_display_enable is called. | ||
176 | */ | ||
177 | if (skip_init) | ||
178 | dss_clk_enable(DSS_CLK_ICK | DSS_CLK_FCK1); | ||
179 | return 0; | 165 | return 0; |
180 | } | 166 | } |
181 | 167 | ||
diff --git a/drivers/video/omap2/dss/venc.c b/drivers/video/omap2/dss/venc.c index eff35050e28a..8e35a5bae429 100644 --- a/drivers/video/omap2/dss/venc.c +++ b/drivers/video/omap2/dss/venc.c | |||
@@ -39,8 +39,6 @@ | |||
39 | 39 | ||
40 | #include "dss.h" | 40 | #include "dss.h" |
41 | 41 | ||
42 | #define VENC_BASE 0x48050C00 | ||
43 | |||
44 | /* Venc registers */ | 42 | /* Venc registers */ |
45 | #define VENC_REV_ID 0x00 | 43 | #define VENC_REV_ID 0x00 |
46 | #define VENC_STATUS 0x04 | 44 | #define VENC_STATUS 0x04 |
@@ -289,6 +287,7 @@ const struct omap_video_timings omap_dss_ntsc_timings = { | |||
289 | EXPORT_SYMBOL(omap_dss_ntsc_timings); | 287 | EXPORT_SYMBOL(omap_dss_ntsc_timings); |
290 | 288 | ||
291 | static struct { | 289 | static struct { |
290 | struct platform_device *pdev; | ||
292 | void __iomem *base; | 291 | void __iomem *base; |
293 | struct mutex venc_lock; | 292 | struct mutex venc_lock; |
294 | u32 wss_data; | 293 | u32 wss_data; |
@@ -381,11 +380,11 @@ static void venc_reset(void) | |||
381 | static void venc_enable_clocks(int enable) | 380 | static void venc_enable_clocks(int enable) |
382 | { | 381 | { |
383 | if (enable) | 382 | if (enable) |
384 | dss_clk_enable(DSS_CLK_ICK | DSS_CLK_FCK1 | DSS_CLK_54M | | 383 | dss_clk_enable(DSS_CLK_ICK | DSS_CLK_FCK | DSS_CLK_TVFCK | |
385 | DSS_CLK_96M); | 384 | DSS_CLK_VIDFCK); |
386 | else | 385 | else |
387 | dss_clk_disable(DSS_CLK_ICK | DSS_CLK_FCK1 | DSS_CLK_54M | | 386 | dss_clk_disable(DSS_CLK_ICK | DSS_CLK_FCK | DSS_CLK_TVFCK | |
388 | DSS_CLK_96M); | 387 | DSS_CLK_VIDFCK); |
389 | } | 388 | } |
390 | 389 | ||
391 | static const struct venc_config *venc_timings_to_config( | 390 | static const struct venc_config *venc_timings_to_config( |
@@ -641,50 +640,23 @@ static struct omap_dss_driver venc_driver = { | |||
641 | }; | 640 | }; |
642 | /* driver end */ | 641 | /* driver end */ |
643 | 642 | ||
644 | 643 | int venc_init_display(struct omap_dss_device *dssdev) | |
645 | |||
646 | int venc_init(struct platform_device *pdev) | ||
647 | { | 644 | { |
648 | u8 rev_id; | 645 | DSSDBG("init_display\n"); |
649 | 646 | ||
650 | mutex_init(&venc.venc_lock); | 647 | if (venc.vdda_dac_reg == NULL) { |
648 | struct regulator *vdda_dac; | ||
651 | 649 | ||
652 | venc.wss_data = 0; | 650 | vdda_dac = regulator_get(&venc.pdev->dev, "vdda_dac"); |
653 | 651 | ||
654 | venc.base = ioremap(VENC_BASE, SZ_1K); | 652 | if (IS_ERR(vdda_dac)) { |
655 | if (!venc.base) { | 653 | DSSERR("can't get VDDA_DAC regulator\n"); |
656 | DSSERR("can't ioremap VENC\n"); | 654 | return PTR_ERR(vdda_dac); |
657 | return -ENOMEM; | 655 | } |
658 | } | ||
659 | 656 | ||
660 | venc.vdda_dac_reg = dss_get_vdda_dac(); | 657 | venc.vdda_dac_reg = vdda_dac; |
661 | if (IS_ERR(venc.vdda_dac_reg)) { | ||
662 | iounmap(venc.base); | ||
663 | DSSERR("can't get VDDA_DAC regulator\n"); | ||
664 | return PTR_ERR(venc.vdda_dac_reg); | ||
665 | } | 658 | } |
666 | 659 | ||
667 | venc_enable_clocks(1); | ||
668 | |||
669 | rev_id = (u8)(venc_read_reg(VENC_REV_ID) & 0xff); | ||
670 | printk(KERN_INFO "OMAP VENC rev %d\n", rev_id); | ||
671 | |||
672 | venc_enable_clocks(0); | ||
673 | |||
674 | return omap_dss_register_driver(&venc_driver); | ||
675 | } | ||
676 | |||
677 | void venc_exit(void) | ||
678 | { | ||
679 | omap_dss_unregister_driver(&venc_driver); | ||
680 | |||
681 | iounmap(venc.base); | ||
682 | } | ||
683 | |||
684 | int venc_init_display(struct omap_dss_device *dssdev) | ||
685 | { | ||
686 | DSSDBG("init_display\n"); | ||
687 | |||
688 | return 0; | 660 | return 0; |
689 | } | 661 | } |
690 | 662 | ||
@@ -740,3 +712,73 @@ void venc_dump_regs(struct seq_file *s) | |||
740 | 712 | ||
741 | #undef DUMPREG | 713 | #undef DUMPREG |
742 | } | 714 | } |
715 | |||
716 | /* VENC HW IP initialisation */ | ||
717 | static int omap_venchw_probe(struct platform_device *pdev) | ||
718 | { | ||
719 | u8 rev_id; | ||
720 | struct resource *venc_mem; | ||
721 | |||
722 | venc.pdev = pdev; | ||
723 | |||
724 | mutex_init(&venc.venc_lock); | ||
725 | |||
726 | venc.wss_data = 0; | ||
727 | |||
728 | venc_mem = platform_get_resource(venc.pdev, IORESOURCE_MEM, 0); | ||
729 | if (!venc_mem) { | ||
730 | DSSERR("can't get IORESOURCE_MEM VENC\n"); | ||
731 | return -EINVAL; | ||
732 | } | ||
733 | venc.base = ioremap(venc_mem->start, resource_size(venc_mem)); | ||
734 | if (!venc.base) { | ||
735 | DSSERR("can't ioremap VENC\n"); | ||
736 | return -ENOMEM; | ||
737 | } | ||
738 | |||
739 | venc_enable_clocks(1); | ||
740 | |||
741 | rev_id = (u8)(venc_read_reg(VENC_REV_ID) & 0xff); | ||
742 | dev_dbg(&pdev->dev, "OMAP VENC rev %d\n", rev_id); | ||
743 | |||
744 | venc_enable_clocks(0); | ||
745 | |||
746 | return omap_dss_register_driver(&venc_driver); | ||
747 | } | ||
748 | |||
749 | static int omap_venchw_remove(struct platform_device *pdev) | ||
750 | { | ||
751 | if (venc.vdda_dac_reg != NULL) { | ||
752 | regulator_put(venc.vdda_dac_reg); | ||
753 | venc.vdda_dac_reg = NULL; | ||
754 | } | ||
755 | omap_dss_unregister_driver(&venc_driver); | ||
756 | |||
757 | iounmap(venc.base); | ||
758 | return 0; | ||
759 | } | ||
760 | |||
761 | static struct platform_driver omap_venchw_driver = { | ||
762 | .probe = omap_venchw_probe, | ||
763 | .remove = omap_venchw_remove, | ||
764 | .driver = { | ||
765 | .name = "omapdss_venc", | ||
766 | .owner = THIS_MODULE, | ||
767 | }, | ||
768 | }; | ||
769 | |||
770 | int venc_init_platform_driver(void) | ||
771 | { | ||
772 | if (cpu_is_omap44xx()) | ||
773 | return 0; | ||
774 | |||
775 | return platform_driver_register(&omap_venchw_driver); | ||
776 | } | ||
777 | |||
778 | void venc_uninit_platform_driver(void) | ||
779 | { | ||
780 | if (cpu_is_omap44xx()) | ||
781 | return; | ||
782 | |||
783 | return platform_driver_unregister(&omap_venchw_driver); | ||
784 | } | ||
diff --git a/drivers/video/omap2/omapfb/Kconfig b/drivers/video/omap2/omapfb/Kconfig index 65149b22cf37..aa33386c81ff 100644 --- a/drivers/video/omap2/omapfb/Kconfig +++ b/drivers/video/omap2/omapfb/Kconfig | |||
@@ -1,5 +1,5 @@ | |||
1 | menuconfig FB_OMAP2 | 1 | menuconfig FB_OMAP2 |
2 | tristate "OMAP2/3 frame buffer support (EXPERIMENTAL)" | 2 | tristate "OMAP2+ frame buffer support (EXPERIMENTAL)" |
3 | depends on FB && OMAP2_DSS | 3 | depends on FB && OMAP2_DSS |
4 | 4 | ||
5 | select OMAP2_VRAM | 5 | select OMAP2_VRAM |
@@ -8,10 +8,10 @@ menuconfig FB_OMAP2 | |||
8 | select FB_CFB_COPYAREA | 8 | select FB_CFB_COPYAREA |
9 | select FB_CFB_IMAGEBLIT | 9 | select FB_CFB_IMAGEBLIT |
10 | help | 10 | help |
11 | Frame buffer driver for OMAP2/3 based boards. | 11 | Frame buffer driver for OMAP2+ based boards. |
12 | 12 | ||
13 | config FB_OMAP2_DEBUG_SUPPORT | 13 | config FB_OMAP2_DEBUG_SUPPORT |
14 | bool "Debug support for OMAP2/3 FB" | 14 | bool "Debug support for OMAP2+ FB" |
15 | default y | 15 | default y |
16 | depends on FB_OMAP2 | 16 | depends on FB_OMAP2 |
17 | help | 17 | help |
diff --git a/drivers/video/omap2/omapfb/omapfb-main.c b/drivers/video/omap2/omapfb/omapfb-main.c index 4fdab8e9c496..505ec6672049 100644 --- a/drivers/video/omap2/omapfb/omapfb-main.c +++ b/drivers/video/omap2/omapfb/omapfb-main.c | |||
@@ -2090,7 +2090,7 @@ static int omapfb_set_def_mode(struct omapfb2_device *fbdev, | |||
2090 | { | 2090 | { |
2091 | int r; | 2091 | int r; |
2092 | u8 bpp; | 2092 | u8 bpp; |
2093 | struct omap_video_timings timings; | 2093 | struct omap_video_timings timings, temp_timings; |
2094 | 2094 | ||
2095 | r = omapfb_mode_to_timings(mode_str, &timings, &bpp); | 2095 | r = omapfb_mode_to_timings(mode_str, &timings, &bpp); |
2096 | if (r) | 2096 | if (r) |
@@ -2100,14 +2100,23 @@ static int omapfb_set_def_mode(struct omapfb2_device *fbdev, | |||
2100 | fbdev->bpp_overrides[fbdev->num_bpp_overrides].bpp = bpp; | 2100 | fbdev->bpp_overrides[fbdev->num_bpp_overrides].bpp = bpp; |
2101 | ++fbdev->num_bpp_overrides; | 2101 | ++fbdev->num_bpp_overrides; |
2102 | 2102 | ||
2103 | if (!display->driver->check_timings || !display->driver->set_timings) | 2103 | if (display->driver->check_timings) { |
2104 | return -EINVAL; | 2104 | r = display->driver->check_timings(display, &timings); |
2105 | if (r) | ||
2106 | return r; | ||
2107 | } else { | ||
2108 | /* If check_timings is not present compare xres and yres */ | ||
2109 | if (display->driver->get_timings) { | ||
2110 | display->driver->get_timings(display, &temp_timings); | ||
2105 | 2111 | ||
2106 | r = display->driver->check_timings(display, &timings); | 2112 | if (temp_timings.x_res != timings.x_res || |
2107 | if (r) | 2113 | temp_timings.y_res != timings.y_res) |
2108 | return r; | 2114 | return -EINVAL; |
2115 | } | ||
2116 | } | ||
2109 | 2117 | ||
2110 | display->driver->set_timings(display, &timings); | 2118 | if (display->driver->set_timings) |
2119 | display->driver->set_timings(display, &timings); | ||
2111 | 2120 | ||
2112 | return 0; | 2121 | return 0; |
2113 | } | 2122 | } |
diff --git a/drivers/video/s3c-fb.c b/drivers/video/s3c-fb.c index 83ce9a04d872..6817d187d46e 100644 --- a/drivers/video/s3c-fb.c +++ b/drivers/video/s3c-fb.c | |||
@@ -1340,6 +1340,7 @@ static int __devinit s3c_fb_probe(struct platform_device *pdev) | |||
1340 | sfb->bus_clk = clk_get(dev, "lcd"); | 1340 | sfb->bus_clk = clk_get(dev, "lcd"); |
1341 | if (IS_ERR(sfb->bus_clk)) { | 1341 | if (IS_ERR(sfb->bus_clk)) { |
1342 | dev_err(dev, "failed to get bus clock\n"); | 1342 | dev_err(dev, "failed to get bus clock\n"); |
1343 | ret = PTR_ERR(sfb->bus_clk); | ||
1343 | goto err_sfb; | 1344 | goto err_sfb; |
1344 | } | 1345 | } |
1345 | 1346 | ||
diff --git a/drivers/video/s3fb.c b/drivers/video/s3fb.c index 75738a928610..ddedad9cd069 100644 --- a/drivers/video/s3fb.c +++ b/drivers/video/s3fb.c | |||
@@ -64,6 +64,8 @@ static const struct svga_fb_format s3fb_formats[] = { | |||
64 | 64 | ||
65 | static const struct svga_pll s3_pll = {3, 129, 3, 33, 0, 3, | 65 | static const struct svga_pll s3_pll = {3, 129, 3, 33, 0, 3, |
66 | 35000, 240000, 14318}; | 66 | 35000, 240000, 14318}; |
67 | static const struct svga_pll s3_trio3d_pll = {3, 129, 3, 31, 0, 4, | ||
68 | 230000, 460000, 14318}; | ||
67 | 69 | ||
68 | static const int s3_memsizes[] = {4096, 0, 3072, 8192, 2048, 6144, 1024, 512}; | 70 | static const int s3_memsizes[] = {4096, 0, 3072, 8192, 2048, 6144, 1024, 512}; |
69 | 71 | ||
@@ -72,7 +74,8 @@ static const char * const s3_names[] = {"S3 Unknown", "S3 Trio32", "S3 Trio64", | |||
72 | "S3 Plato/PX", "S3 Aurora64VP", "S3 Virge", | 74 | "S3 Plato/PX", "S3 Aurora64VP", "S3 Virge", |
73 | "S3 Virge/VX", "S3 Virge/DX", "S3 Virge/GX", | 75 | "S3 Virge/VX", "S3 Virge/DX", "S3 Virge/GX", |
74 | "S3 Virge/GX2", "S3 Virge/GX2P", "S3 Virge/GX2P", | 76 | "S3 Virge/GX2", "S3 Virge/GX2P", "S3 Virge/GX2P", |
75 | "S3 Trio3D/1X", "S3 Trio3D/2X", "S3 Trio3D/2X"}; | 77 | "S3 Trio3D/1X", "S3 Trio3D/2X", "S3 Trio3D/2X", |
78 | "S3 Trio3D"}; | ||
76 | 79 | ||
77 | #define CHIP_UNKNOWN 0x00 | 80 | #define CHIP_UNKNOWN 0x00 |
78 | #define CHIP_732_TRIO32 0x01 | 81 | #define CHIP_732_TRIO32 0x01 |
@@ -93,6 +96,7 @@ static const char * const s3_names[] = {"S3 Unknown", "S3 Trio32", "S3 Trio64", | |||
93 | #define CHIP_360_TRIO3D_1X 0x10 | 96 | #define CHIP_360_TRIO3D_1X 0x10 |
94 | #define CHIP_362_TRIO3D_2X 0x11 | 97 | #define CHIP_362_TRIO3D_2X 0x11 |
95 | #define CHIP_368_TRIO3D_2X 0x12 | 98 | #define CHIP_368_TRIO3D_2X 0x12 |
99 | #define CHIP_365_TRIO3D 0x13 | ||
96 | 100 | ||
97 | #define CHIP_XXX_TRIO 0x80 | 101 | #define CHIP_XXX_TRIO 0x80 |
98 | #define CHIP_XXX_TRIO64V2_DXGX 0x81 | 102 | #define CHIP_XXX_TRIO64V2_DXGX 0x81 |
@@ -119,9 +123,11 @@ static const struct vga_regset s3_v_sync_start_regs[] = {{0x10, 0, 7}, {0x07, | |||
119 | static const struct vga_regset s3_v_sync_end_regs[] = {{0x11, 0, 3}, VGA_REGSET_END}; | 123 | static const struct vga_regset s3_v_sync_end_regs[] = {{0x11, 0, 3}, VGA_REGSET_END}; |
120 | 124 | ||
121 | static const struct vga_regset s3_line_compare_regs[] = {{0x18, 0, 7}, {0x07, 4, 4}, {0x09, 6, 6}, {0x5E, 6, 6}, VGA_REGSET_END}; | 125 | static const struct vga_regset s3_line_compare_regs[] = {{0x18, 0, 7}, {0x07, 4, 4}, {0x09, 6, 6}, {0x5E, 6, 6}, VGA_REGSET_END}; |
122 | static const struct vga_regset s3_start_address_regs[] = {{0x0d, 0, 7}, {0x0c, 0, 7}, {0x31, 4, 5}, {0x51, 0, 1}, VGA_REGSET_END}; | 126 | static const struct vga_regset s3_start_address_regs[] = {{0x0d, 0, 7}, {0x0c, 0, 7}, {0x69, 0, 4}, VGA_REGSET_END}; |
123 | static const struct vga_regset s3_offset_regs[] = {{0x13, 0, 7}, {0x51, 4, 5}, VGA_REGSET_END}; /* set 0x43 bit 2 to 0 */ | 127 | static const struct vga_regset s3_offset_regs[] = {{0x13, 0, 7}, {0x51, 4, 5}, VGA_REGSET_END}; /* set 0x43 bit 2 to 0 */ |
124 | 128 | ||
129 | static const struct vga_regset s3_dtpc_regs[] = {{0x3B, 0, 7}, {0x5D, 6, 6}, VGA_REGSET_END}; | ||
130 | |||
125 | static const struct svga_timing_regs s3_timing_regs = { | 131 | static const struct svga_timing_regs s3_timing_regs = { |
126 | s3_h_total_regs, s3_h_display_regs, s3_h_blank_start_regs, | 132 | s3_h_total_regs, s3_h_display_regs, s3_h_blank_start_regs, |
127 | s3_h_blank_end_regs, s3_h_sync_start_regs, s3_h_sync_end_regs, | 133 | s3_h_blank_end_regs, s3_h_sync_start_regs, s3_h_sync_end_regs, |
@@ -188,12 +194,19 @@ static void s3fb_settile_fast(struct fb_info *info, struct fb_tilemap *map) | |||
188 | } | 194 | } |
189 | } | 195 | } |
190 | 196 | ||
197 | static void s3fb_tilecursor(struct fb_info *info, struct fb_tilecursor *cursor) | ||
198 | { | ||
199 | struct s3fb_info *par = info->par; | ||
200 | |||
201 | svga_tilecursor(par->state.vgabase, info, cursor); | ||
202 | } | ||
203 | |||
191 | static struct fb_tile_ops s3fb_tile_ops = { | 204 | static struct fb_tile_ops s3fb_tile_ops = { |
192 | .fb_settile = svga_settile, | 205 | .fb_settile = svga_settile, |
193 | .fb_tilecopy = svga_tilecopy, | 206 | .fb_tilecopy = svga_tilecopy, |
194 | .fb_tilefill = svga_tilefill, | 207 | .fb_tilefill = svga_tilefill, |
195 | .fb_tileblit = svga_tileblit, | 208 | .fb_tileblit = svga_tileblit, |
196 | .fb_tilecursor = svga_tilecursor, | 209 | .fb_tilecursor = s3fb_tilecursor, |
197 | .fb_get_tilemax = svga_get_tilemax, | 210 | .fb_get_tilemax = svga_get_tilemax, |
198 | }; | 211 | }; |
199 | 212 | ||
@@ -202,7 +215,7 @@ static struct fb_tile_ops s3fb_fast_tile_ops = { | |||
202 | .fb_tilecopy = svga_tilecopy, | 215 | .fb_tilecopy = svga_tilecopy, |
203 | .fb_tilefill = svga_tilefill, | 216 | .fb_tilefill = svga_tilefill, |
204 | .fb_tileblit = svga_tileblit, | 217 | .fb_tileblit = svga_tileblit, |
205 | .fb_tilecursor = svga_tilecursor, | 218 | .fb_tilecursor = s3fb_tilecursor, |
206 | .fb_get_tilemax = svga_get_tilemax, | 219 | .fb_get_tilemax = svga_get_tilemax, |
207 | }; | 220 | }; |
208 | 221 | ||
@@ -334,33 +347,34 @@ static void s3_set_pixclock(struct fb_info *info, u32 pixclock) | |||
334 | u8 regval; | 347 | u8 regval; |
335 | int rv; | 348 | int rv; |
336 | 349 | ||
337 | rv = svga_compute_pll(&s3_pll, 1000000000 / pixclock, &m, &n, &r, info->node); | 350 | rv = svga_compute_pll((par->chip == CHIP_365_TRIO3D) ? &s3_trio3d_pll : &s3_pll, |
351 | 1000000000 / pixclock, &m, &n, &r, info->node); | ||
338 | if (rv < 0) { | 352 | if (rv < 0) { |
339 | printk(KERN_ERR "fb%d: cannot set requested pixclock, keeping old value\n", info->node); | 353 | printk(KERN_ERR "fb%d: cannot set requested pixclock, keeping old value\n", info->node); |
340 | return; | 354 | return; |
341 | } | 355 | } |
342 | 356 | ||
343 | /* Set VGA misc register */ | 357 | /* Set VGA misc register */ |
344 | regval = vga_r(NULL, VGA_MIS_R); | 358 | regval = vga_r(par->state.vgabase, VGA_MIS_R); |
345 | vga_w(NULL, VGA_MIS_W, regval | VGA_MIS_ENB_PLL_LOAD); | 359 | vga_w(par->state.vgabase, VGA_MIS_W, regval | VGA_MIS_ENB_PLL_LOAD); |
346 | 360 | ||
347 | /* Set S3 clock registers */ | 361 | /* Set S3 clock registers */ |
348 | if (par->chip == CHIP_360_TRIO3D_1X || | 362 | if (par->chip == CHIP_360_TRIO3D_1X || |
349 | par->chip == CHIP_362_TRIO3D_2X || | 363 | par->chip == CHIP_362_TRIO3D_2X || |
350 | par->chip == CHIP_368_TRIO3D_2X) { | 364 | par->chip == CHIP_368_TRIO3D_2X) { |
351 | vga_wseq(NULL, 0x12, (n - 2) | ((r & 3) << 6)); /* n and two bits of r */ | 365 | vga_wseq(par->state.vgabase, 0x12, (n - 2) | ((r & 3) << 6)); /* n and two bits of r */ |
352 | vga_wseq(NULL, 0x29, r >> 2); /* remaining highest bit of r */ | 366 | vga_wseq(par->state.vgabase, 0x29, r >> 2); /* remaining highest bit of r */ |
353 | } else | 367 | } else |
354 | vga_wseq(NULL, 0x12, (n - 2) | (r << 5)); | 368 | vga_wseq(par->state.vgabase, 0x12, (n - 2) | (r << 5)); |
355 | vga_wseq(NULL, 0x13, m - 2); | 369 | vga_wseq(par->state.vgabase, 0x13, m - 2); |
356 | 370 | ||
357 | udelay(1000); | 371 | udelay(1000); |
358 | 372 | ||
359 | /* Activate clock - write 0, 1, 0 to seq/15 bit 5 */ | 373 | /* Activate clock - write 0, 1, 0 to seq/15 bit 5 */ |
360 | regval = vga_rseq (NULL, 0x15); /* | 0x80; */ | 374 | regval = vga_rseq (par->state.vgabase, 0x15); /* | 0x80; */ |
361 | vga_wseq(NULL, 0x15, regval & ~(1<<5)); | 375 | vga_wseq(par->state.vgabase, 0x15, regval & ~(1<<5)); |
362 | vga_wseq(NULL, 0x15, regval | (1<<5)); | 376 | vga_wseq(par->state.vgabase, 0x15, regval | (1<<5)); |
363 | vga_wseq(NULL, 0x15, regval & ~(1<<5)); | 377 | vga_wseq(par->state.vgabase, 0x15, regval & ~(1<<5)); |
364 | } | 378 | } |
365 | 379 | ||
366 | 380 | ||
@@ -372,7 +386,10 @@ static int s3fb_open(struct fb_info *info, int user) | |||
372 | 386 | ||
373 | mutex_lock(&(par->open_lock)); | 387 | mutex_lock(&(par->open_lock)); |
374 | if (par->ref_count == 0) { | 388 | if (par->ref_count == 0) { |
389 | void __iomem *vgabase = par->state.vgabase; | ||
390 | |||
375 | memset(&(par->state), 0, sizeof(struct vgastate)); | 391 | memset(&(par->state), 0, sizeof(struct vgastate)); |
392 | par->state.vgabase = vgabase; | ||
376 | par->state.flags = VGA_SAVE_MODE | VGA_SAVE_FONTS | VGA_SAVE_CMAP; | 393 | par->state.flags = VGA_SAVE_MODE | VGA_SAVE_FONTS | VGA_SAVE_CMAP; |
377 | par->state.num_crtc = 0x70; | 394 | par->state.num_crtc = 0x70; |
378 | par->state.num_seq = 0x20; | 395 | par->state.num_seq = 0x20; |
@@ -470,6 +487,7 @@ static int s3fb_set_par(struct fb_info *info) | |||
470 | struct s3fb_info *par = info->par; | 487 | struct s3fb_info *par = info->par; |
471 | u32 value, mode, hmul, offset_value, screen_size, multiplex, dbytes; | 488 | u32 value, mode, hmul, offset_value, screen_size, multiplex, dbytes; |
472 | u32 bpp = info->var.bits_per_pixel; | 489 | u32 bpp = info->var.bits_per_pixel; |
490 | u32 htotal, hsstart; | ||
473 | 491 | ||
474 | if (bpp != 0) { | 492 | if (bpp != 0) { |
475 | info->fix.ypanstep = 1; | 493 | info->fix.ypanstep = 1; |
@@ -504,99 +522,112 @@ static int s3fb_set_par(struct fb_info *info) | |||
504 | info->var.activate = FB_ACTIVATE_NOW; | 522 | info->var.activate = FB_ACTIVATE_NOW; |
505 | 523 | ||
506 | /* Unlock registers */ | 524 | /* Unlock registers */ |
507 | vga_wcrt(NULL, 0x38, 0x48); | 525 | vga_wcrt(par->state.vgabase, 0x38, 0x48); |
508 | vga_wcrt(NULL, 0x39, 0xA5); | 526 | vga_wcrt(par->state.vgabase, 0x39, 0xA5); |
509 | vga_wseq(NULL, 0x08, 0x06); | 527 | vga_wseq(par->state.vgabase, 0x08, 0x06); |
510 | svga_wcrt_mask(0x11, 0x00, 0x80); | 528 | svga_wcrt_mask(par->state.vgabase, 0x11, 0x00, 0x80); |
511 | 529 | ||
512 | /* Blank screen and turn off sync */ | 530 | /* Blank screen and turn off sync */ |
513 | svga_wseq_mask(0x01, 0x20, 0x20); | 531 | svga_wseq_mask(par->state.vgabase, 0x01, 0x20, 0x20); |
514 | svga_wcrt_mask(0x17, 0x00, 0x80); | 532 | svga_wcrt_mask(par->state.vgabase, 0x17, 0x00, 0x80); |
515 | 533 | ||
516 | /* Set default values */ | 534 | /* Set default values */ |
517 | svga_set_default_gfx_regs(); | 535 | svga_set_default_gfx_regs(par->state.vgabase); |
518 | svga_set_default_atc_regs(); | 536 | svga_set_default_atc_regs(par->state.vgabase); |
519 | svga_set_default_seq_regs(); | 537 | svga_set_default_seq_regs(par->state.vgabase); |
520 | svga_set_default_crt_regs(); | 538 | svga_set_default_crt_regs(par->state.vgabase); |
521 | svga_wcrt_multi(s3_line_compare_regs, 0xFFFFFFFF); | 539 | svga_wcrt_multi(par->state.vgabase, s3_line_compare_regs, 0xFFFFFFFF); |
522 | svga_wcrt_multi(s3_start_address_regs, 0); | 540 | svga_wcrt_multi(par->state.vgabase, s3_start_address_regs, 0); |
523 | 541 | ||
524 | /* S3 specific initialization */ | 542 | /* S3 specific initialization */ |
525 | svga_wcrt_mask(0x58, 0x10, 0x10); /* enable linear framebuffer */ | 543 | svga_wcrt_mask(par->state.vgabase, 0x58, 0x10, 0x10); /* enable linear framebuffer */ |
526 | svga_wcrt_mask(0x31, 0x08, 0x08); /* enable sequencer access to framebuffer above 256 kB */ | 544 | svga_wcrt_mask(par->state.vgabase, 0x31, 0x08, 0x08); /* enable sequencer access to framebuffer above 256 kB */ |
527 | 545 | ||
528 | /* svga_wcrt_mask(0x33, 0x08, 0x08); */ /* DDR ? */ | 546 | /* svga_wcrt_mask(par->state.vgabase, 0x33, 0x08, 0x08); */ /* DDR ? */ |
529 | /* svga_wcrt_mask(0x43, 0x01, 0x01); */ /* DDR ? */ | 547 | /* svga_wcrt_mask(par->state.vgabase, 0x43, 0x01, 0x01); */ /* DDR ? */ |
530 | svga_wcrt_mask(0x33, 0x00, 0x08); /* no DDR ? */ | 548 | svga_wcrt_mask(par->state.vgabase, 0x33, 0x00, 0x08); /* no DDR ? */ |
531 | svga_wcrt_mask(0x43, 0x00, 0x01); /* no DDR ? */ | 549 | svga_wcrt_mask(par->state.vgabase, 0x43, 0x00, 0x01); /* no DDR ? */ |
532 | 550 | ||
533 | svga_wcrt_mask(0x5D, 0x00, 0x28); /* Clear strange HSlen bits */ | 551 | svga_wcrt_mask(par->state.vgabase, 0x5D, 0x00, 0x28); /* Clear strange HSlen bits */ |
534 | 552 | ||
535 | /* svga_wcrt_mask(0x58, 0x03, 0x03); */ | 553 | /* svga_wcrt_mask(par->state.vgabase, 0x58, 0x03, 0x03); */ |
536 | 554 | ||
537 | /* svga_wcrt_mask(0x53, 0x12, 0x13); */ /* enable MMIO */ | 555 | /* svga_wcrt_mask(par->state.vgabase, 0x53, 0x12, 0x13); */ /* enable MMIO */ |
538 | /* svga_wcrt_mask(0x40, 0x08, 0x08); */ /* enable write buffer */ | 556 | /* svga_wcrt_mask(par->state.vgabase, 0x40, 0x08, 0x08); */ /* enable write buffer */ |
539 | 557 | ||
540 | 558 | ||
541 | /* Set the offset register */ | 559 | /* Set the offset register */ |
542 | pr_debug("fb%d: offset register : %d\n", info->node, offset_value); | 560 | pr_debug("fb%d: offset register : %d\n", info->node, offset_value); |
543 | svga_wcrt_multi(s3_offset_regs, offset_value); | 561 | svga_wcrt_multi(par->state.vgabase, s3_offset_regs, offset_value); |
544 | 562 | ||
545 | if (par->chip != CHIP_360_TRIO3D_1X && | 563 | if (par->chip != CHIP_360_TRIO3D_1X && |
546 | par->chip != CHIP_362_TRIO3D_2X && | 564 | par->chip != CHIP_362_TRIO3D_2X && |
547 | par->chip != CHIP_368_TRIO3D_2X) { | 565 | par->chip != CHIP_368_TRIO3D_2X) { |
548 | vga_wcrt(NULL, 0x54, 0x18); /* M parameter */ | 566 | vga_wcrt(par->state.vgabase, 0x54, 0x18); /* M parameter */ |
549 | vga_wcrt(NULL, 0x60, 0xff); /* N parameter */ | 567 | vga_wcrt(par->state.vgabase, 0x60, 0xff); /* N parameter */ |
550 | vga_wcrt(NULL, 0x61, 0xff); /* L parameter */ | 568 | vga_wcrt(par->state.vgabase, 0x61, 0xff); /* L parameter */ |
551 | vga_wcrt(NULL, 0x62, 0xff); /* L parameter */ | 569 | vga_wcrt(par->state.vgabase, 0x62, 0xff); /* L parameter */ |
552 | } | 570 | } |
553 | 571 | ||
554 | vga_wcrt(NULL, 0x3A, 0x35); | 572 | vga_wcrt(par->state.vgabase, 0x3A, 0x35); |
555 | svga_wattr(0x33, 0x00); | 573 | svga_wattr(par->state.vgabase, 0x33, 0x00); |
556 | 574 | ||
557 | if (info->var.vmode & FB_VMODE_DOUBLE) | 575 | if (info->var.vmode & FB_VMODE_DOUBLE) |
558 | svga_wcrt_mask(0x09, 0x80, 0x80); | 576 | svga_wcrt_mask(par->state.vgabase, 0x09, 0x80, 0x80); |
559 | else | 577 | else |
560 | svga_wcrt_mask(0x09, 0x00, 0x80); | 578 | svga_wcrt_mask(par->state.vgabase, 0x09, 0x00, 0x80); |
561 | 579 | ||
562 | if (info->var.vmode & FB_VMODE_INTERLACED) | 580 | if (info->var.vmode & FB_VMODE_INTERLACED) |
563 | svga_wcrt_mask(0x42, 0x20, 0x20); | 581 | svga_wcrt_mask(par->state.vgabase, 0x42, 0x20, 0x20); |
564 | else | 582 | else |
565 | svga_wcrt_mask(0x42, 0x00, 0x20); | 583 | svga_wcrt_mask(par->state.vgabase, 0x42, 0x00, 0x20); |
566 | 584 | ||
567 | /* Disable hardware graphics cursor */ | 585 | /* Disable hardware graphics cursor */ |
568 | svga_wcrt_mask(0x45, 0x00, 0x01); | 586 | svga_wcrt_mask(par->state.vgabase, 0x45, 0x00, 0x01); |
569 | /* Disable Streams engine */ | 587 | /* Disable Streams engine */ |
570 | svga_wcrt_mask(0x67, 0x00, 0x0C); | 588 | svga_wcrt_mask(par->state.vgabase, 0x67, 0x00, 0x0C); |
571 | 589 | ||
572 | mode = svga_match_format(s3fb_formats, &(info->var), &(info->fix)); | 590 | mode = svga_match_format(s3fb_formats, &(info->var), &(info->fix)); |
573 | 591 | ||
574 | /* S3 virge DX hack */ | 592 | /* S3 virge DX hack */ |
575 | if (par->chip == CHIP_375_VIRGE_DX) { | 593 | if (par->chip == CHIP_375_VIRGE_DX) { |
576 | vga_wcrt(NULL, 0x86, 0x80); | 594 | vga_wcrt(par->state.vgabase, 0x86, 0x80); |
577 | vga_wcrt(NULL, 0x90, 0x00); | 595 | vga_wcrt(par->state.vgabase, 0x90, 0x00); |
578 | } | 596 | } |
579 | 597 | ||
580 | /* S3 virge VX hack */ | 598 | /* S3 virge VX hack */ |
581 | if (par->chip == CHIP_988_VIRGE_VX) { | 599 | if (par->chip == CHIP_988_VIRGE_VX) { |
582 | vga_wcrt(NULL, 0x50, 0x00); | 600 | vga_wcrt(par->state.vgabase, 0x50, 0x00); |
583 | vga_wcrt(NULL, 0x67, 0x50); | 601 | vga_wcrt(par->state.vgabase, 0x67, 0x50); |
584 | 602 | ||
585 | vga_wcrt(NULL, 0x63, (mode <= 2) ? 0x90 : 0x09); | 603 | vga_wcrt(par->state.vgabase, 0x63, (mode <= 2) ? 0x90 : 0x09); |
586 | vga_wcrt(NULL, 0x66, 0x90); | 604 | vga_wcrt(par->state.vgabase, 0x66, 0x90); |
587 | } | 605 | } |
588 | 606 | ||
589 | if (par->chip == CHIP_360_TRIO3D_1X || | 607 | if (par->chip == CHIP_360_TRIO3D_1X || |
590 | par->chip == CHIP_362_TRIO3D_2X || | 608 | par->chip == CHIP_362_TRIO3D_2X || |
591 | par->chip == CHIP_368_TRIO3D_2X) { | 609 | par->chip == CHIP_368_TRIO3D_2X || |
610 | par->chip == CHIP_365_TRIO3D || | ||
611 | par->chip == CHIP_375_VIRGE_DX || | ||
612 | par->chip == CHIP_385_VIRGE_GX) { | ||
592 | dbytes = info->var.xres * ((bpp+7)/8); | 613 | dbytes = info->var.xres * ((bpp+7)/8); |
593 | vga_wcrt(NULL, 0x91, (dbytes + 7) / 8); | 614 | vga_wcrt(par->state.vgabase, 0x91, (dbytes + 7) / 8); |
594 | vga_wcrt(NULL, 0x90, (((dbytes + 7) / 8) >> 8) | 0x80); | 615 | vga_wcrt(par->state.vgabase, 0x90, (((dbytes + 7) / 8) >> 8) | 0x80); |
595 | 616 | ||
596 | vga_wcrt(NULL, 0x66, 0x81); | 617 | vga_wcrt(par->state.vgabase, 0x66, 0x81); |
597 | } | 618 | } |
598 | 619 | ||
599 | svga_wcrt_mask(0x31, 0x00, 0x40); | 620 | if (par->chip == CHIP_356_VIRGE_GX2 || |
621 | par->chip == CHIP_357_VIRGE_GX2P || | ||
622 | par->chip == CHIP_359_VIRGE_GX2P || | ||
623 | par->chip == CHIP_360_TRIO3D_1X || | ||
624 | par->chip == CHIP_362_TRIO3D_2X || | ||
625 | par->chip == CHIP_368_TRIO3D_2X) | ||
626 | vga_wcrt(par->state.vgabase, 0x34, 0x00); | ||
627 | else /* enable Data Transfer Position Control (DTPC) */ | ||
628 | vga_wcrt(par->state.vgabase, 0x34, 0x10); | ||
629 | |||
630 | svga_wcrt_mask(par->state.vgabase, 0x31, 0x00, 0x40); | ||
600 | multiplex = 0; | 631 | multiplex = 0; |
601 | hmul = 1; | 632 | hmul = 1; |
602 | 633 | ||
@@ -604,51 +635,51 @@ static int s3fb_set_par(struct fb_info *info) | |||
604 | switch (mode) { | 635 | switch (mode) { |
605 | case 0: | 636 | case 0: |
606 | pr_debug("fb%d: text mode\n", info->node); | 637 | pr_debug("fb%d: text mode\n", info->node); |
607 | svga_set_textmode_vga_regs(); | 638 | svga_set_textmode_vga_regs(par->state.vgabase); |
608 | 639 | ||
609 | /* Set additional registers like in 8-bit mode */ | 640 | /* Set additional registers like in 8-bit mode */ |
610 | svga_wcrt_mask(0x50, 0x00, 0x30); | 641 | svga_wcrt_mask(par->state.vgabase, 0x50, 0x00, 0x30); |
611 | svga_wcrt_mask(0x67, 0x00, 0xF0); | 642 | svga_wcrt_mask(par->state.vgabase, 0x67, 0x00, 0xF0); |
612 | 643 | ||
613 | /* Disable enhanced mode */ | 644 | /* Disable enhanced mode */ |
614 | svga_wcrt_mask(0x3A, 0x00, 0x30); | 645 | svga_wcrt_mask(par->state.vgabase, 0x3A, 0x00, 0x30); |
615 | 646 | ||
616 | if (fasttext) { | 647 | if (fasttext) { |
617 | pr_debug("fb%d: high speed text mode set\n", info->node); | 648 | pr_debug("fb%d: high speed text mode set\n", info->node); |
618 | svga_wcrt_mask(0x31, 0x40, 0x40); | 649 | svga_wcrt_mask(par->state.vgabase, 0x31, 0x40, 0x40); |
619 | } | 650 | } |
620 | break; | 651 | break; |
621 | case 1: | 652 | case 1: |
622 | pr_debug("fb%d: 4 bit pseudocolor\n", info->node); | 653 | pr_debug("fb%d: 4 bit pseudocolor\n", info->node); |
623 | vga_wgfx(NULL, VGA_GFX_MODE, 0x40); | 654 | vga_wgfx(par->state.vgabase, VGA_GFX_MODE, 0x40); |
624 | 655 | ||
625 | /* Set additional registers like in 8-bit mode */ | 656 | /* Set additional registers like in 8-bit mode */ |
626 | svga_wcrt_mask(0x50, 0x00, 0x30); | 657 | svga_wcrt_mask(par->state.vgabase, 0x50, 0x00, 0x30); |
627 | svga_wcrt_mask(0x67, 0x00, 0xF0); | 658 | svga_wcrt_mask(par->state.vgabase, 0x67, 0x00, 0xF0); |
628 | 659 | ||
629 | /* disable enhanced mode */ | 660 | /* disable enhanced mode */ |
630 | svga_wcrt_mask(0x3A, 0x00, 0x30); | 661 | svga_wcrt_mask(par->state.vgabase, 0x3A, 0x00, 0x30); |
631 | break; | 662 | break; |
632 | case 2: | 663 | case 2: |
633 | pr_debug("fb%d: 4 bit pseudocolor, planar\n", info->node); | 664 | pr_debug("fb%d: 4 bit pseudocolor, planar\n", info->node); |
634 | 665 | ||
635 | /* Set additional registers like in 8-bit mode */ | 666 | /* Set additional registers like in 8-bit mode */ |
636 | svga_wcrt_mask(0x50, 0x00, 0x30); | 667 | svga_wcrt_mask(par->state.vgabase, 0x50, 0x00, 0x30); |
637 | svga_wcrt_mask(0x67, 0x00, 0xF0); | 668 | svga_wcrt_mask(par->state.vgabase, 0x67, 0x00, 0xF0); |
638 | 669 | ||
639 | /* disable enhanced mode */ | 670 | /* disable enhanced mode */ |
640 | svga_wcrt_mask(0x3A, 0x00, 0x30); | 671 | svga_wcrt_mask(par->state.vgabase, 0x3A, 0x00, 0x30); |
641 | break; | 672 | break; |
642 | case 3: | 673 | case 3: |
643 | pr_debug("fb%d: 8 bit pseudocolor\n", info->node); | 674 | pr_debug("fb%d: 8 bit pseudocolor\n", info->node); |
644 | svga_wcrt_mask(0x50, 0x00, 0x30); | 675 | svga_wcrt_mask(par->state.vgabase, 0x50, 0x00, 0x30); |
645 | if (info->var.pixclock > 20000 || | 676 | if (info->var.pixclock > 20000 || |
646 | par->chip == CHIP_360_TRIO3D_1X || | 677 | par->chip == CHIP_360_TRIO3D_1X || |
647 | par->chip == CHIP_362_TRIO3D_2X || | 678 | par->chip == CHIP_362_TRIO3D_2X || |
648 | par->chip == CHIP_368_TRIO3D_2X) | 679 | par->chip == CHIP_368_TRIO3D_2X) |
649 | svga_wcrt_mask(0x67, 0x00, 0xF0); | 680 | svga_wcrt_mask(par->state.vgabase, 0x67, 0x00, 0xF0); |
650 | else { | 681 | else { |
651 | svga_wcrt_mask(0x67, 0x10, 0xF0); | 682 | svga_wcrt_mask(par->state.vgabase, 0x67, 0x10, 0xF0); |
652 | multiplex = 1; | 683 | multiplex = 1; |
653 | } | 684 | } |
654 | break; | 685 | break; |
@@ -656,12 +687,21 @@ static int s3fb_set_par(struct fb_info *info) | |||
656 | pr_debug("fb%d: 5/5/5 truecolor\n", info->node); | 687 | pr_debug("fb%d: 5/5/5 truecolor\n", info->node); |
657 | if (par->chip == CHIP_988_VIRGE_VX) { | 688 | if (par->chip == CHIP_988_VIRGE_VX) { |
658 | if (info->var.pixclock > 20000) | 689 | if (info->var.pixclock > 20000) |
659 | svga_wcrt_mask(0x67, 0x20, 0xF0); | 690 | svga_wcrt_mask(par->state.vgabase, 0x67, 0x20, 0xF0); |
660 | else | 691 | else |
661 | svga_wcrt_mask(0x67, 0x30, 0xF0); | 692 | svga_wcrt_mask(par->state.vgabase, 0x67, 0x30, 0xF0); |
693 | } else if (par->chip == CHIP_365_TRIO3D) { | ||
694 | svga_wcrt_mask(par->state.vgabase, 0x50, 0x10, 0x30); | ||
695 | if (info->var.pixclock > 8695) { | ||
696 | svga_wcrt_mask(par->state.vgabase, 0x67, 0x30, 0xF0); | ||
697 | hmul = 2; | ||
698 | } else { | ||
699 | svga_wcrt_mask(par->state.vgabase, 0x67, 0x20, 0xF0); | ||
700 | multiplex = 1; | ||
701 | } | ||
662 | } else { | 702 | } else { |
663 | svga_wcrt_mask(0x50, 0x10, 0x30); | 703 | svga_wcrt_mask(par->state.vgabase, 0x50, 0x10, 0x30); |
664 | svga_wcrt_mask(0x67, 0x30, 0xF0); | 704 | svga_wcrt_mask(par->state.vgabase, 0x67, 0x30, 0xF0); |
665 | if (par->chip != CHIP_360_TRIO3D_1X && | 705 | if (par->chip != CHIP_360_TRIO3D_1X && |
666 | par->chip != CHIP_362_TRIO3D_2X && | 706 | par->chip != CHIP_362_TRIO3D_2X && |
667 | par->chip != CHIP_368_TRIO3D_2X) | 707 | par->chip != CHIP_368_TRIO3D_2X) |
@@ -672,12 +712,21 @@ static int s3fb_set_par(struct fb_info *info) | |||
672 | pr_debug("fb%d: 5/6/5 truecolor\n", info->node); | 712 | pr_debug("fb%d: 5/6/5 truecolor\n", info->node); |
673 | if (par->chip == CHIP_988_VIRGE_VX) { | 713 | if (par->chip == CHIP_988_VIRGE_VX) { |
674 | if (info->var.pixclock > 20000) | 714 | if (info->var.pixclock > 20000) |
675 | svga_wcrt_mask(0x67, 0x40, 0xF0); | 715 | svga_wcrt_mask(par->state.vgabase, 0x67, 0x40, 0xF0); |
676 | else | 716 | else |
677 | svga_wcrt_mask(0x67, 0x50, 0xF0); | 717 | svga_wcrt_mask(par->state.vgabase, 0x67, 0x50, 0xF0); |
718 | } else if (par->chip == CHIP_365_TRIO3D) { | ||
719 | svga_wcrt_mask(par->state.vgabase, 0x50, 0x10, 0x30); | ||
720 | if (info->var.pixclock > 8695) { | ||
721 | svga_wcrt_mask(par->state.vgabase, 0x67, 0x50, 0xF0); | ||
722 | hmul = 2; | ||
723 | } else { | ||
724 | svga_wcrt_mask(par->state.vgabase, 0x67, 0x40, 0xF0); | ||
725 | multiplex = 1; | ||
726 | } | ||
678 | } else { | 727 | } else { |
679 | svga_wcrt_mask(0x50, 0x10, 0x30); | 728 | svga_wcrt_mask(par->state.vgabase, 0x50, 0x10, 0x30); |
680 | svga_wcrt_mask(0x67, 0x50, 0xF0); | 729 | svga_wcrt_mask(par->state.vgabase, 0x67, 0x50, 0xF0); |
681 | if (par->chip != CHIP_360_TRIO3D_1X && | 730 | if (par->chip != CHIP_360_TRIO3D_1X && |
682 | par->chip != CHIP_362_TRIO3D_2X && | 731 | par->chip != CHIP_362_TRIO3D_2X && |
683 | par->chip != CHIP_368_TRIO3D_2X) | 732 | par->chip != CHIP_368_TRIO3D_2X) |
@@ -687,12 +736,12 @@ static int s3fb_set_par(struct fb_info *info) | |||
687 | case 6: | 736 | case 6: |
688 | /* VIRGE VX case */ | 737 | /* VIRGE VX case */ |
689 | pr_debug("fb%d: 8/8/8 truecolor\n", info->node); | 738 | pr_debug("fb%d: 8/8/8 truecolor\n", info->node); |
690 | svga_wcrt_mask(0x67, 0xD0, 0xF0); | 739 | svga_wcrt_mask(par->state.vgabase, 0x67, 0xD0, 0xF0); |
691 | break; | 740 | break; |
692 | case 7: | 741 | case 7: |
693 | pr_debug("fb%d: 8/8/8/8 truecolor\n", info->node); | 742 | pr_debug("fb%d: 8/8/8/8 truecolor\n", info->node); |
694 | svga_wcrt_mask(0x50, 0x30, 0x30); | 743 | svga_wcrt_mask(par->state.vgabase, 0x50, 0x30, 0x30); |
695 | svga_wcrt_mask(0x67, 0xD0, 0xF0); | 744 | svga_wcrt_mask(par->state.vgabase, 0x67, 0xD0, 0xF0); |
696 | break; | 745 | break; |
697 | default: | 746 | default: |
698 | printk(KERN_ERR "fb%d: unsupported mode - bug\n", info->node); | 747 | printk(KERN_ERR "fb%d: unsupported mode - bug\n", info->node); |
@@ -700,25 +749,30 @@ static int s3fb_set_par(struct fb_info *info) | |||
700 | } | 749 | } |
701 | 750 | ||
702 | if (par->chip != CHIP_988_VIRGE_VX) { | 751 | if (par->chip != CHIP_988_VIRGE_VX) { |
703 | svga_wseq_mask(0x15, multiplex ? 0x10 : 0x00, 0x10); | 752 | svga_wseq_mask(par->state.vgabase, 0x15, multiplex ? 0x10 : 0x00, 0x10); |
704 | svga_wseq_mask(0x18, multiplex ? 0x80 : 0x00, 0x80); | 753 | svga_wseq_mask(par->state.vgabase, 0x18, multiplex ? 0x80 : 0x00, 0x80); |
705 | } | 754 | } |
706 | 755 | ||
707 | s3_set_pixclock(info, info->var.pixclock); | 756 | s3_set_pixclock(info, info->var.pixclock); |
708 | svga_set_timings(&s3_timing_regs, &(info->var), hmul, 1, | 757 | svga_set_timings(par->state.vgabase, &s3_timing_regs, &(info->var), hmul, 1, |
709 | (info->var.vmode & FB_VMODE_DOUBLE) ? 2 : 1, | 758 | (info->var.vmode & FB_VMODE_DOUBLE) ? 2 : 1, |
710 | (info->var.vmode & FB_VMODE_INTERLACED) ? 2 : 1, | 759 | (info->var.vmode & FB_VMODE_INTERLACED) ? 2 : 1, |
711 | hmul, info->node); | 760 | hmul, info->node); |
712 | 761 | ||
713 | /* Set interlaced mode start/end register */ | 762 | /* Set interlaced mode start/end register */ |
714 | value = info->var.xres + info->var.left_margin + info->var.right_margin + info->var.hsync_len; | 763 | htotal = info->var.xres + info->var.left_margin + info->var.right_margin + info->var.hsync_len; |
715 | value = ((value * hmul) / 8) - 5; | 764 | htotal = ((htotal * hmul) / 8) - 5; |
716 | vga_wcrt(NULL, 0x3C, (value + 1) / 2); | 765 | vga_wcrt(par->state.vgabase, 0x3C, (htotal + 1) / 2); |
766 | |||
767 | /* Set Data Transfer Position */ | ||
768 | hsstart = ((info->var.xres + info->var.right_margin) * hmul) / 8; | ||
769 | value = clamp((htotal + hsstart + 1) / 2, hsstart + 4, htotal + 1); | ||
770 | svga_wcrt_multi(par->state.vgabase, s3_dtpc_regs, value); | ||
717 | 771 | ||
718 | memset_io(info->screen_base, 0x00, screen_size); | 772 | memset_io(info->screen_base, 0x00, screen_size); |
719 | /* Device and screen back on */ | 773 | /* Device and screen back on */ |
720 | svga_wcrt_mask(0x17, 0x80, 0x80); | 774 | svga_wcrt_mask(par->state.vgabase, 0x17, 0x80, 0x80); |
721 | svga_wseq_mask(0x01, 0x00, 0x20); | 775 | svga_wseq_mask(par->state.vgabase, 0x01, 0x00, 0x20); |
722 | 776 | ||
723 | return 0; | 777 | return 0; |
724 | } | 778 | } |
@@ -788,31 +842,33 @@ static int s3fb_setcolreg(u_int regno, u_int red, u_int green, u_int blue, | |||
788 | 842 | ||
789 | static int s3fb_blank(int blank_mode, struct fb_info *info) | 843 | static int s3fb_blank(int blank_mode, struct fb_info *info) |
790 | { | 844 | { |
845 | struct s3fb_info *par = info->par; | ||
846 | |||
791 | switch (blank_mode) { | 847 | switch (blank_mode) { |
792 | case FB_BLANK_UNBLANK: | 848 | case FB_BLANK_UNBLANK: |
793 | pr_debug("fb%d: unblank\n", info->node); | 849 | pr_debug("fb%d: unblank\n", info->node); |
794 | svga_wcrt_mask(0x56, 0x00, 0x06); | 850 | svga_wcrt_mask(par->state.vgabase, 0x56, 0x00, 0x06); |
795 | svga_wseq_mask(0x01, 0x00, 0x20); | 851 | svga_wseq_mask(par->state.vgabase, 0x01, 0x00, 0x20); |
796 | break; | 852 | break; |
797 | case FB_BLANK_NORMAL: | 853 | case FB_BLANK_NORMAL: |
798 | pr_debug("fb%d: blank\n", info->node); | 854 | pr_debug("fb%d: blank\n", info->node); |
799 | svga_wcrt_mask(0x56, 0x00, 0x06); | 855 | svga_wcrt_mask(par->state.vgabase, 0x56, 0x00, 0x06); |
800 | svga_wseq_mask(0x01, 0x20, 0x20); | 856 | svga_wseq_mask(par->state.vgabase, 0x01, 0x20, 0x20); |
801 | break; | 857 | break; |
802 | case FB_BLANK_HSYNC_SUSPEND: | 858 | case FB_BLANK_HSYNC_SUSPEND: |
803 | pr_debug("fb%d: hsync\n", info->node); | 859 | pr_debug("fb%d: hsync\n", info->node); |
804 | svga_wcrt_mask(0x56, 0x02, 0x06); | 860 | svga_wcrt_mask(par->state.vgabase, 0x56, 0x02, 0x06); |
805 | svga_wseq_mask(0x01, 0x20, 0x20); | 861 | svga_wseq_mask(par->state.vgabase, 0x01, 0x20, 0x20); |
806 | break; | 862 | break; |
807 | case FB_BLANK_VSYNC_SUSPEND: | 863 | case FB_BLANK_VSYNC_SUSPEND: |
808 | pr_debug("fb%d: vsync\n", info->node); | 864 | pr_debug("fb%d: vsync\n", info->node); |
809 | svga_wcrt_mask(0x56, 0x04, 0x06); | 865 | svga_wcrt_mask(par->state.vgabase, 0x56, 0x04, 0x06); |
810 | svga_wseq_mask(0x01, 0x20, 0x20); | 866 | svga_wseq_mask(par->state.vgabase, 0x01, 0x20, 0x20); |
811 | break; | 867 | break; |
812 | case FB_BLANK_POWERDOWN: | 868 | case FB_BLANK_POWERDOWN: |
813 | pr_debug("fb%d: sync down\n", info->node); | 869 | pr_debug("fb%d: sync down\n", info->node); |
814 | svga_wcrt_mask(0x56, 0x06, 0x06); | 870 | svga_wcrt_mask(par->state.vgabase, 0x56, 0x06, 0x06); |
815 | svga_wseq_mask(0x01, 0x20, 0x20); | 871 | svga_wseq_mask(par->state.vgabase, 0x01, 0x20, 0x20); |
816 | break; | 872 | break; |
817 | } | 873 | } |
818 | 874 | ||
@@ -822,8 +878,9 @@ static int s3fb_blank(int blank_mode, struct fb_info *info) | |||
822 | 878 | ||
823 | /* Pan the display */ | 879 | /* Pan the display */ |
824 | 880 | ||
825 | static int s3fb_pan_display(struct fb_var_screeninfo *var, struct fb_info *info) { | 881 | static int s3fb_pan_display(struct fb_var_screeninfo *var, struct fb_info *info) |
826 | 882 | { | |
883 | struct s3fb_info *par = info->par; | ||
827 | unsigned int offset; | 884 | unsigned int offset; |
828 | 885 | ||
829 | /* Calculate the offset */ | 886 | /* Calculate the offset */ |
@@ -837,7 +894,7 @@ static int s3fb_pan_display(struct fb_var_screeninfo *var, struct fb_info *info) | |||
837 | } | 894 | } |
838 | 895 | ||
839 | /* Set the offset */ | 896 | /* Set the offset */ |
840 | svga_wcrt_multi(s3_start_address_regs, offset); | 897 | svga_wcrt_multi(par->state.vgabase, s3_start_address_regs, offset); |
841 | 898 | ||
842 | return 0; | 899 | return 0; |
843 | } | 900 | } |
@@ -863,12 +920,14 @@ static struct fb_ops s3fb_ops = { | |||
863 | 920 | ||
864 | /* ------------------------------------------------------------------------- */ | 921 | /* ------------------------------------------------------------------------- */ |
865 | 922 | ||
866 | static int __devinit s3_identification(int chip) | 923 | static int __devinit s3_identification(struct s3fb_info *par) |
867 | { | 924 | { |
925 | int chip = par->chip; | ||
926 | |||
868 | if (chip == CHIP_XXX_TRIO) { | 927 | if (chip == CHIP_XXX_TRIO) { |
869 | u8 cr30 = vga_rcrt(NULL, 0x30); | 928 | u8 cr30 = vga_rcrt(par->state.vgabase, 0x30); |
870 | u8 cr2e = vga_rcrt(NULL, 0x2e); | 929 | u8 cr2e = vga_rcrt(par->state.vgabase, 0x2e); |
871 | u8 cr2f = vga_rcrt(NULL, 0x2f); | 930 | u8 cr2f = vga_rcrt(par->state.vgabase, 0x2f); |
872 | 931 | ||
873 | if ((cr30 == 0xE0) || (cr30 == 0xE1)) { | 932 | if ((cr30 == 0xE0) || (cr30 == 0xE1)) { |
874 | if (cr2e == 0x10) | 933 | if (cr2e == 0x10) |
@@ -883,7 +942,7 @@ static int __devinit s3_identification(int chip) | |||
883 | } | 942 | } |
884 | 943 | ||
885 | if (chip == CHIP_XXX_TRIO64V2_DXGX) { | 944 | if (chip == CHIP_XXX_TRIO64V2_DXGX) { |
886 | u8 cr6f = vga_rcrt(NULL, 0x6f); | 945 | u8 cr6f = vga_rcrt(par->state.vgabase, 0x6f); |
887 | 946 | ||
888 | if (! (cr6f & 0x01)) | 947 | if (! (cr6f & 0x01)) |
889 | return CHIP_775_TRIO64V2_DX; | 948 | return CHIP_775_TRIO64V2_DX; |
@@ -892,7 +951,7 @@ static int __devinit s3_identification(int chip) | |||
892 | } | 951 | } |
893 | 952 | ||
894 | if (chip == CHIP_XXX_VIRGE_DXGX) { | 953 | if (chip == CHIP_XXX_VIRGE_DXGX) { |
895 | u8 cr6f = vga_rcrt(NULL, 0x6f); | 954 | u8 cr6f = vga_rcrt(par->state.vgabase, 0x6f); |
896 | 955 | ||
897 | if (! (cr6f & 0x01)) | 956 | if (! (cr6f & 0x01)) |
898 | return CHIP_375_VIRGE_DX; | 957 | return CHIP_375_VIRGE_DX; |
@@ -901,7 +960,7 @@ static int __devinit s3_identification(int chip) | |||
901 | } | 960 | } |
902 | 961 | ||
903 | if (chip == CHIP_36X_TRIO3D_1X_2X) { | 962 | if (chip == CHIP_36X_TRIO3D_1X_2X) { |
904 | switch (vga_rcrt(NULL, 0x2f)) { | 963 | switch (vga_rcrt(par->state.vgabase, 0x2f)) { |
905 | case 0x00: | 964 | case 0x00: |
906 | return CHIP_360_TRIO3D_1X; | 965 | return CHIP_360_TRIO3D_1X; |
907 | case 0x01: | 966 | case 0x01: |
@@ -919,6 +978,8 @@ static int __devinit s3_identification(int chip) | |||
919 | 978 | ||
920 | static int __devinit s3_pci_probe(struct pci_dev *dev, const struct pci_device_id *id) | 979 | static int __devinit s3_pci_probe(struct pci_dev *dev, const struct pci_device_id *id) |
921 | { | 980 | { |
981 | struct pci_bus_region bus_reg; | ||
982 | struct resource vga_res; | ||
922 | struct fb_info *info; | 983 | struct fb_info *info; |
923 | struct s3fb_info *par; | 984 | struct s3fb_info *par; |
924 | int rc; | 985 | int rc; |
@@ -968,31 +1029,42 @@ static int __devinit s3_pci_probe(struct pci_dev *dev, const struct pci_device_i | |||
968 | goto err_iomap; | 1029 | goto err_iomap; |
969 | } | 1030 | } |
970 | 1031 | ||
1032 | bus_reg.start = 0; | ||
1033 | bus_reg.end = 64 * 1024; | ||
1034 | |||
1035 | vga_res.flags = IORESOURCE_IO; | ||
1036 | |||
1037 | pcibios_bus_to_resource(dev, &vga_res, &bus_reg); | ||
1038 | |||
1039 | par->state.vgabase = (void __iomem *) vga_res.start; | ||
1040 | |||
971 | /* Unlock regs */ | 1041 | /* Unlock regs */ |
972 | cr38 = vga_rcrt(NULL, 0x38); | 1042 | cr38 = vga_rcrt(par->state.vgabase, 0x38); |
973 | cr39 = vga_rcrt(NULL, 0x39); | 1043 | cr39 = vga_rcrt(par->state.vgabase, 0x39); |
974 | vga_wseq(NULL, 0x08, 0x06); | 1044 | vga_wseq(par->state.vgabase, 0x08, 0x06); |
975 | vga_wcrt(NULL, 0x38, 0x48); | 1045 | vga_wcrt(par->state.vgabase, 0x38, 0x48); |
976 | vga_wcrt(NULL, 0x39, 0xA5); | 1046 | vga_wcrt(par->state.vgabase, 0x39, 0xA5); |
977 | 1047 | ||
978 | /* Identify chip type */ | 1048 | /* Identify chip type */ |
979 | par->chip = id->driver_data & CHIP_MASK; | 1049 | par->chip = id->driver_data & CHIP_MASK; |
980 | par->rev = vga_rcrt(NULL, 0x2f); | 1050 | par->rev = vga_rcrt(par->state.vgabase, 0x2f); |
981 | if (par->chip & CHIP_UNDECIDED_FLAG) | 1051 | if (par->chip & CHIP_UNDECIDED_FLAG) |
982 | par->chip = s3_identification(par->chip); | 1052 | par->chip = s3_identification(par); |
983 | 1053 | ||
984 | /* Find how many physical memory there is on card */ | 1054 | /* Find how many physical memory there is on card */ |
985 | /* 0x36 register is accessible even if other registers are locked */ | 1055 | /* 0x36 register is accessible even if other registers are locked */ |
986 | regval = vga_rcrt(NULL, 0x36); | 1056 | regval = vga_rcrt(par->state.vgabase, 0x36); |
987 | if (par->chip == CHIP_360_TRIO3D_1X || | 1057 | if (par->chip == CHIP_360_TRIO3D_1X || |
988 | par->chip == CHIP_362_TRIO3D_2X || | 1058 | par->chip == CHIP_362_TRIO3D_2X || |
989 | par->chip == CHIP_368_TRIO3D_2X) { | 1059 | par->chip == CHIP_368_TRIO3D_2X || |
1060 | par->chip == CHIP_365_TRIO3D) { | ||
990 | switch ((regval & 0xE0) >> 5) { | 1061 | switch ((regval & 0xE0) >> 5) { |
991 | case 0: /* 8MB -- only 4MB usable for display */ | 1062 | case 0: /* 8MB -- only 4MB usable for display */ |
992 | case 1: /* 4MB with 32-bit bus */ | 1063 | case 1: /* 4MB with 32-bit bus */ |
993 | case 2: /* 4MB */ | 1064 | case 2: /* 4MB */ |
994 | info->screen_size = 4 << 20; | 1065 | info->screen_size = 4 << 20; |
995 | break; | 1066 | break; |
1067 | case 4: /* 2MB on 365 Trio3D */ | ||
996 | case 6: /* 2MB */ | 1068 | case 6: /* 2MB */ |
997 | info->screen_size = 2 << 20; | 1069 | info->screen_size = 2 << 20; |
998 | break; | 1070 | break; |
@@ -1002,13 +1074,13 @@ static int __devinit s3_pci_probe(struct pci_dev *dev, const struct pci_device_i | |||
1002 | info->fix.smem_len = info->screen_size; | 1074 | info->fix.smem_len = info->screen_size; |
1003 | 1075 | ||
1004 | /* Find MCLK frequency */ | 1076 | /* Find MCLK frequency */ |
1005 | regval = vga_rseq(NULL, 0x10); | 1077 | regval = vga_rseq(par->state.vgabase, 0x10); |
1006 | par->mclk_freq = ((vga_rseq(NULL, 0x11) + 2) * 14318) / ((regval & 0x1F) + 2); | 1078 | par->mclk_freq = ((vga_rseq(par->state.vgabase, 0x11) + 2) * 14318) / ((regval & 0x1F) + 2); |
1007 | par->mclk_freq = par->mclk_freq >> (regval >> 5); | 1079 | par->mclk_freq = par->mclk_freq >> (regval >> 5); |
1008 | 1080 | ||
1009 | /* Restore locks */ | 1081 | /* Restore locks */ |
1010 | vga_wcrt(NULL, 0x38, cr38); | 1082 | vga_wcrt(par->state.vgabase, 0x38, cr38); |
1011 | vga_wcrt(NULL, 0x39, cr39); | 1083 | vga_wcrt(par->state.vgabase, 0x39, cr39); |
1012 | 1084 | ||
1013 | strcpy(info->fix.id, s3_names [par->chip]); | 1085 | strcpy(info->fix.id, s3_names [par->chip]); |
1014 | info->fix.mmio_start = 0; | 1086 | info->fix.mmio_start = 0; |
@@ -1027,6 +1099,14 @@ static int __devinit s3_pci_probe(struct pci_dev *dev, const struct pci_device_i | |||
1027 | goto err_find_mode; | 1099 | goto err_find_mode; |
1028 | } | 1100 | } |
1029 | 1101 | ||
1102 | /* maximize virtual vertical size for fast scrolling */ | ||
1103 | info->var.yres_virtual = info->fix.smem_len * 8 / | ||
1104 | (info->var.bits_per_pixel * info->var.xres_virtual); | ||
1105 | if (info->var.yres_virtual < info->var.yres) { | ||
1106 | dev_err(info->device, "virtual vertical size smaller than real\n"); | ||
1107 | goto err_find_mode; | ||
1108 | } | ||
1109 | |||
1030 | rc = fb_alloc_cmap(&info->cmap, 256, 0); | 1110 | rc = fb_alloc_cmap(&info->cmap, 256, 0); |
1031 | if (rc < 0) { | 1111 | if (rc < 0) { |
1032 | dev_err(info->device, "cannot allocate colormap\n"); | 1112 | dev_err(info->device, "cannot allocate colormap\n"); |
@@ -1044,8 +1124,8 @@ static int __devinit s3_pci_probe(struct pci_dev *dev, const struct pci_device_i | |||
1044 | 1124 | ||
1045 | if (par->chip == CHIP_UNKNOWN) | 1125 | if (par->chip == CHIP_UNKNOWN) |
1046 | printk(KERN_INFO "fb%d: unknown chip, CR2D=%x, CR2E=%x, CRT2F=%x, CRT30=%x\n", | 1126 | printk(KERN_INFO "fb%d: unknown chip, CR2D=%x, CR2E=%x, CRT2F=%x, CRT30=%x\n", |
1047 | info->node, vga_rcrt(NULL, 0x2d), vga_rcrt(NULL, 0x2e), | 1127 | info->node, vga_rcrt(par->state.vgabase, 0x2d), vga_rcrt(par->state.vgabase, 0x2e), |
1048 | vga_rcrt(NULL, 0x2f), vga_rcrt(NULL, 0x30)); | 1128 | vga_rcrt(par->state.vgabase, 0x2f), vga_rcrt(par->state.vgabase, 0x30)); |
1049 | 1129 | ||
1050 | /* Record a reference to the driver data */ | 1130 | /* Record a reference to the driver data */ |
1051 | pci_set_drvdata(dev, info); | 1131 | pci_set_drvdata(dev, info); |
@@ -1192,6 +1272,7 @@ static struct pci_device_id s3_devices[] __devinitdata = { | |||
1192 | {PCI_DEVICE(PCI_VENDOR_ID_S3, 0x8A11), .driver_data = CHIP_357_VIRGE_GX2P}, | 1272 | {PCI_DEVICE(PCI_VENDOR_ID_S3, 0x8A11), .driver_data = CHIP_357_VIRGE_GX2P}, |
1193 | {PCI_DEVICE(PCI_VENDOR_ID_S3, 0x8A12), .driver_data = CHIP_359_VIRGE_GX2P}, | 1273 | {PCI_DEVICE(PCI_VENDOR_ID_S3, 0x8A12), .driver_data = CHIP_359_VIRGE_GX2P}, |
1194 | {PCI_DEVICE(PCI_VENDOR_ID_S3, 0x8A13), .driver_data = CHIP_36X_TRIO3D_1X_2X}, | 1274 | {PCI_DEVICE(PCI_VENDOR_ID_S3, 0x8A13), .driver_data = CHIP_36X_TRIO3D_1X_2X}, |
1275 | {PCI_DEVICE(PCI_VENDOR_ID_S3, 0x8904), .driver_data = CHIP_365_TRIO3D}, | ||
1195 | 1276 | ||
1196 | {0, 0, 0, 0, 0, 0, 0} | 1277 | {0, 0, 0, 0, 0, 0, 0} |
1197 | }; | 1278 | }; |
diff --git a/drivers/video/sh7760fb.c b/drivers/video/sh7760fb.c index bea38fce2470..8fe19582c460 100644 --- a/drivers/video/sh7760fb.c +++ b/drivers/video/sh7760fb.c | |||
@@ -459,14 +459,14 @@ static int __devinit sh7760fb_probe(struct platform_device *pdev) | |||
459 | } | 459 | } |
460 | 460 | ||
461 | par->ioarea = request_mem_region(res->start, | 461 | par->ioarea = request_mem_region(res->start, |
462 | (res->end - res->start), pdev->name); | 462 | resource_size(res), pdev->name); |
463 | if (!par->ioarea) { | 463 | if (!par->ioarea) { |
464 | dev_err(&pdev->dev, "mmio area busy\n"); | 464 | dev_err(&pdev->dev, "mmio area busy\n"); |
465 | ret = -EBUSY; | 465 | ret = -EBUSY; |
466 | goto out_fb; | 466 | goto out_fb; |
467 | } | 467 | } |
468 | 468 | ||
469 | par->base = ioremap_nocache(res->start, res->end - res->start + 1); | 469 | par->base = ioremap_nocache(res->start, resource_size(res)); |
470 | if (!par->base) { | 470 | if (!par->base) { |
471 | dev_err(&pdev->dev, "cannot remap\n"); | 471 | dev_err(&pdev->dev, "cannot remap\n"); |
472 | ret = -ENODEV; | 472 | ret = -ENODEV; |
diff --git a/drivers/video/sh_mobile_lcdcfb.c b/drivers/video/sh_mobile_lcdcfb.c index bf2629f83f40..757665bc500f 100644 --- a/drivers/video/sh_mobile_lcdcfb.c +++ b/drivers/video/sh_mobile_lcdcfb.c | |||
@@ -1088,8 +1088,9 @@ static struct backlight_device *sh_mobile_lcdc_bl_probe(struct device *parent, | |||
1088 | 1088 | ||
1089 | bl = backlight_device_register(ch->cfg.bl_info.name, parent, ch, | 1089 | bl = backlight_device_register(ch->cfg.bl_info.name, parent, ch, |
1090 | &sh_mobile_lcdc_bl_ops, NULL); | 1090 | &sh_mobile_lcdc_bl_ops, NULL); |
1091 | if (!bl) { | 1091 | if (IS_ERR(bl)) { |
1092 | dev_err(parent, "unable to register backlight device\n"); | 1092 | dev_err(parent, "unable to register backlight device: %ld\n", |
1093 | PTR_ERR(bl)); | ||
1093 | return NULL; | 1094 | return NULL; |
1094 | } | 1095 | } |
1095 | 1096 | ||
diff --git a/drivers/video/sis/sis.h b/drivers/video/sis/sis.h index eac7a01925f3..1987f1b7212f 100644 --- a/drivers/video/sis/sis.h +++ b/drivers/video/sis/sis.h | |||
@@ -495,6 +495,7 @@ struct sis_video_info { | |||
495 | unsigned int refresh_rate; | 495 | unsigned int refresh_rate; |
496 | 496 | ||
497 | unsigned int chip; | 497 | unsigned int chip; |
498 | unsigned int chip_real_id; | ||
498 | u8 revision_id; | 499 | u8 revision_id; |
499 | int sisvga_enabled; /* PCI device was enabled */ | 500 | int sisvga_enabled; /* PCI device was enabled */ |
500 | 501 | ||
diff --git a/drivers/video/sis/sis_main.c b/drivers/video/sis/sis_main.c index 2fb8c5a660fb..75259845933d 100644 --- a/drivers/video/sis/sis_main.c +++ b/drivers/video/sis/sis_main.c | |||
@@ -4563,6 +4563,11 @@ sisfb_post_sis315330(struct pci_dev *pdev) | |||
4563 | } | 4563 | } |
4564 | #endif | 4564 | #endif |
4565 | 4565 | ||
4566 | static inline int sisfb_xgi_is21(struct sis_video_info *ivideo) | ||
4567 | { | ||
4568 | return ivideo->chip_real_id == XGI_21; | ||
4569 | } | ||
4570 | |||
4566 | static void __devinit | 4571 | static void __devinit |
4567 | sisfb_post_xgi_delay(struct sis_video_info *ivideo, int delay) | 4572 | sisfb_post_xgi_delay(struct sis_video_info *ivideo, int delay) |
4568 | { | 4573 | { |
@@ -4627,11 +4632,11 @@ sisfb_post_xgi_rwtest(struct sis_video_info *ivideo, int starta, | |||
4627 | return 1; | 4632 | return 1; |
4628 | } | 4633 | } |
4629 | 4634 | ||
4630 | static void __devinit | 4635 | static int __devinit |
4631 | sisfb_post_xgi_ramsize(struct sis_video_info *ivideo) | 4636 | sisfb_post_xgi_ramsize(struct sis_video_info *ivideo) |
4632 | { | 4637 | { |
4633 | unsigned int buswidth, ranksize, channelab, mapsize; | 4638 | unsigned int buswidth, ranksize, channelab, mapsize; |
4634 | int i, j, k, l; | 4639 | int i, j, k, l, status; |
4635 | u8 reg, sr14; | 4640 | u8 reg, sr14; |
4636 | static const u8 dramsr13[12 * 5] = { | 4641 | static const u8 dramsr13[12 * 5] = { |
4637 | 0x02, 0x0e, 0x0b, 0x80, 0x5d, | 4642 | 0x02, 0x0e, 0x0b, 0x80, 0x5d, |
@@ -4673,7 +4678,7 @@ sisfb_post_xgi_ramsize(struct sis_video_info *ivideo) | |||
4673 | SiS_SetReg(SISSR, 0x13, 0x35); | 4678 | SiS_SetReg(SISSR, 0x13, 0x35); |
4674 | SiS_SetReg(SISSR, 0x14, 0x41); | 4679 | SiS_SetReg(SISSR, 0x14, 0x41); |
4675 | /* TODO */ | 4680 | /* TODO */ |
4676 | return; | 4681 | return -ENOMEM; |
4677 | } | 4682 | } |
4678 | 4683 | ||
4679 | /* Non-interleaving */ | 4684 | /* Non-interleaving */ |
@@ -4835,6 +4840,7 @@ bail_out: | |||
4835 | 4840 | ||
4836 | j = (ivideo->chip == XGI_20) ? 5 : 9; | 4841 | j = (ivideo->chip == XGI_20) ? 5 : 9; |
4837 | k = (ivideo->chip == XGI_20) ? 12 : 4; | 4842 | k = (ivideo->chip == XGI_20) ? 12 : 4; |
4843 | status = -EIO; | ||
4838 | 4844 | ||
4839 | for(i = 0; i < k; i++) { | 4845 | for(i = 0; i < k; i++) { |
4840 | 4846 | ||
@@ -4868,11 +4874,15 @@ bail_out: | |||
4868 | SiS_SetRegANDOR(SISSR, 0x14, 0x0f, (reg & 0xf0)); | 4874 | SiS_SetRegANDOR(SISSR, 0x14, 0x0f, (reg & 0xf0)); |
4869 | sisfb_post_xgi_delay(ivideo, 1); | 4875 | sisfb_post_xgi_delay(ivideo, 1); |
4870 | 4876 | ||
4871 | if(sisfb_post_xgi_rwtest(ivideo, j, ((reg >> 4) + channelab - 2 + 20), mapsize)) | 4877 | if (sisfb_post_xgi_rwtest(ivideo, j, ((reg >> 4) + channelab - 2 + 20), mapsize)) { |
4878 | status = 0; | ||
4872 | break; | 4879 | break; |
4880 | } | ||
4873 | } | 4881 | } |
4874 | 4882 | ||
4875 | iounmap(ivideo->video_vbase); | 4883 | iounmap(ivideo->video_vbase); |
4884 | |||
4885 | return status; | ||
4876 | } | 4886 | } |
4877 | 4887 | ||
4878 | static void __devinit | 4888 | static void __devinit |
@@ -4931,6 +4941,175 @@ sisfb_post_xgi_setclocks(struct sis_video_info *ivideo, u8 regb) | |||
4931 | sisfb_post_xgi_delay(ivideo, 0x43); | 4941 | sisfb_post_xgi_delay(ivideo, 0x43); |
4932 | } | 4942 | } |
4933 | 4943 | ||
4944 | static void __devinit | ||
4945 | sisfb_post_xgi_ddr2_mrs_default(struct sis_video_info *ivideo, u8 regb) | ||
4946 | { | ||
4947 | unsigned char *bios = ivideo->bios_abase; | ||
4948 | u8 v1; | ||
4949 | |||
4950 | SiS_SetReg(SISSR, 0x28, 0x64); | ||
4951 | SiS_SetReg(SISSR, 0x29, 0x63); | ||
4952 | sisfb_post_xgi_delay(ivideo, 15); | ||
4953 | SiS_SetReg(SISSR, 0x18, 0x00); | ||
4954 | SiS_SetReg(SISSR, 0x19, 0x20); | ||
4955 | SiS_SetReg(SISSR, 0x16, 0x00); | ||
4956 | SiS_SetReg(SISSR, 0x16, 0x80); | ||
4957 | SiS_SetReg(SISSR, 0x18, 0xc5); | ||
4958 | SiS_SetReg(SISSR, 0x19, 0x23); | ||
4959 | SiS_SetReg(SISSR, 0x16, 0x00); | ||
4960 | SiS_SetReg(SISSR, 0x16, 0x80); | ||
4961 | sisfb_post_xgi_delay(ivideo, 1); | ||
4962 | SiS_SetReg(SISCR, 0x97, 0x11); | ||
4963 | sisfb_post_xgi_setclocks(ivideo, regb); | ||
4964 | sisfb_post_xgi_delay(ivideo, 0x46); | ||
4965 | SiS_SetReg(SISSR, 0x18, 0xc5); | ||
4966 | SiS_SetReg(SISSR, 0x19, 0x23); | ||
4967 | SiS_SetReg(SISSR, 0x16, 0x00); | ||
4968 | SiS_SetReg(SISSR, 0x16, 0x80); | ||
4969 | sisfb_post_xgi_delay(ivideo, 1); | ||
4970 | SiS_SetReg(SISSR, 0x1b, 0x04); | ||
4971 | sisfb_post_xgi_delay(ivideo, 1); | ||
4972 | SiS_SetReg(SISSR, 0x1b, 0x00); | ||
4973 | sisfb_post_xgi_delay(ivideo, 1); | ||
4974 | v1 = 0x31; | ||
4975 | if (ivideo->haveXGIROM) { | ||
4976 | v1 = bios[0xf0]; | ||
4977 | } | ||
4978 | SiS_SetReg(SISSR, 0x18, v1); | ||
4979 | SiS_SetReg(SISSR, 0x19, 0x06); | ||
4980 | SiS_SetReg(SISSR, 0x16, 0x04); | ||
4981 | SiS_SetReg(SISSR, 0x16, 0x84); | ||
4982 | sisfb_post_xgi_delay(ivideo, 1); | ||
4983 | } | ||
4984 | |||
4985 | static void __devinit | ||
4986 | sisfb_post_xgi_ddr2_mrs_xg21(struct sis_video_info *ivideo) | ||
4987 | { | ||
4988 | sisfb_post_xgi_setclocks(ivideo, 1); | ||
4989 | |||
4990 | SiS_SetReg(SISCR, 0x97, 0x11); | ||
4991 | sisfb_post_xgi_delay(ivideo, 0x46); | ||
4992 | |||
4993 | SiS_SetReg(SISSR, 0x18, 0x00); /* EMRS2 */ | ||
4994 | SiS_SetReg(SISSR, 0x19, 0x80); | ||
4995 | SiS_SetReg(SISSR, 0x16, 0x05); | ||
4996 | SiS_SetReg(SISSR, 0x16, 0x85); | ||
4997 | |||
4998 | SiS_SetReg(SISSR, 0x18, 0x00); /* EMRS3 */ | ||
4999 | SiS_SetReg(SISSR, 0x19, 0xc0); | ||
5000 | SiS_SetReg(SISSR, 0x16, 0x05); | ||
5001 | SiS_SetReg(SISSR, 0x16, 0x85); | ||
5002 | |||
5003 | SiS_SetReg(SISSR, 0x18, 0x00); /* EMRS1 */ | ||
5004 | SiS_SetReg(SISSR, 0x19, 0x40); | ||
5005 | SiS_SetReg(SISSR, 0x16, 0x05); | ||
5006 | SiS_SetReg(SISSR, 0x16, 0x85); | ||
5007 | |||
5008 | SiS_SetReg(SISSR, 0x18, 0x42); /* MRS1 */ | ||
5009 | SiS_SetReg(SISSR, 0x19, 0x02); | ||
5010 | SiS_SetReg(SISSR, 0x16, 0x05); | ||
5011 | SiS_SetReg(SISSR, 0x16, 0x85); | ||
5012 | sisfb_post_xgi_delay(ivideo, 1); | ||
5013 | |||
5014 | SiS_SetReg(SISSR, 0x1b, 0x04); | ||
5015 | sisfb_post_xgi_delay(ivideo, 1); | ||
5016 | |||
5017 | SiS_SetReg(SISSR, 0x1b, 0x00); | ||
5018 | sisfb_post_xgi_delay(ivideo, 1); | ||
5019 | |||
5020 | SiS_SetReg(SISSR, 0x18, 0x42); /* MRS1 */ | ||
5021 | SiS_SetReg(SISSR, 0x19, 0x00); | ||
5022 | SiS_SetReg(SISSR, 0x16, 0x05); | ||
5023 | SiS_SetReg(SISSR, 0x16, 0x85); | ||
5024 | sisfb_post_xgi_delay(ivideo, 1); | ||
5025 | } | ||
5026 | |||
5027 | static void __devinit | ||
5028 | sisfb_post_xgi_ddr2(struct sis_video_info *ivideo, u8 regb) | ||
5029 | { | ||
5030 | unsigned char *bios = ivideo->bios_abase; | ||
5031 | static const u8 cs158[8] = { | ||
5032 | 0x88, 0xaa, 0x48, 0x00, 0x00, 0x00, 0x00, 0x00 | ||
5033 | }; | ||
5034 | static const u8 cs160[8] = { | ||
5035 | 0x44, 0x77, 0x77, 0x00, 0x00, 0x00, 0x00, 0x00 | ||
5036 | }; | ||
5037 | static const u8 cs168[8] = { | ||
5038 | 0x48, 0x78, 0x88, 0x00, 0x00, 0x00, 0x00, 0x00 | ||
5039 | }; | ||
5040 | u8 reg; | ||
5041 | u8 v1; | ||
5042 | u8 v2; | ||
5043 | u8 v3; | ||
5044 | |||
5045 | SiS_SetReg(SISCR, 0xb0, 0x80); /* DDR2 dual frequency mode */ | ||
5046 | SiS_SetReg(SISCR, 0x82, 0x77); | ||
5047 | SiS_SetReg(SISCR, 0x86, 0x00); | ||
5048 | reg = SiS_GetReg(SISCR, 0x86); | ||
5049 | SiS_SetReg(SISCR, 0x86, 0x88); | ||
5050 | reg = SiS_GetReg(SISCR, 0x86); | ||
5051 | v1 = cs168[regb]; v2 = cs160[regb]; v3 = cs158[regb]; | ||
5052 | if (ivideo->haveXGIROM) { | ||
5053 | v1 = bios[regb + 0x168]; | ||
5054 | v2 = bios[regb + 0x160]; | ||
5055 | v3 = bios[regb + 0x158]; | ||
5056 | } | ||
5057 | SiS_SetReg(SISCR, 0x86, v1); | ||
5058 | SiS_SetReg(SISCR, 0x82, 0x77); | ||
5059 | SiS_SetReg(SISCR, 0x85, 0x00); | ||
5060 | reg = SiS_GetReg(SISCR, 0x85); | ||
5061 | SiS_SetReg(SISCR, 0x85, 0x88); | ||
5062 | reg = SiS_GetReg(SISCR, 0x85); | ||
5063 | SiS_SetReg(SISCR, 0x85, v2); | ||
5064 | SiS_SetReg(SISCR, 0x82, v3); | ||
5065 | SiS_SetReg(SISCR, 0x98, 0x01); | ||
5066 | SiS_SetReg(SISCR, 0x9a, 0x02); | ||
5067 | if (sisfb_xgi_is21(ivideo)) | ||
5068 | sisfb_post_xgi_ddr2_mrs_xg21(ivideo); | ||
5069 | else | ||
5070 | sisfb_post_xgi_ddr2_mrs_default(ivideo, regb); | ||
5071 | } | ||
5072 | |||
5073 | static u8 __devinit | ||
5074 | sisfb_post_xgi_ramtype(struct sis_video_info *ivideo) | ||
5075 | { | ||
5076 | unsigned char *bios = ivideo->bios_abase; | ||
5077 | u8 ramtype; | ||
5078 | u8 reg; | ||
5079 | u8 v1; | ||
5080 | |||
5081 | ramtype = 0x00; v1 = 0x10; | ||
5082 | if (ivideo->haveXGIROM) { | ||
5083 | ramtype = bios[0x62]; | ||
5084 | v1 = bios[0x1d2]; | ||
5085 | } | ||
5086 | if (!(ramtype & 0x80)) { | ||
5087 | if (sisfb_xgi_is21(ivideo)) { | ||
5088 | SiS_SetRegAND(SISCR, 0xb4, 0xfd); /* GPIO control */ | ||
5089 | SiS_SetRegOR(SISCR, 0x4a, 0x80); /* GPIOH EN */ | ||
5090 | reg = SiS_GetReg(SISCR, 0x48); | ||
5091 | SiS_SetRegOR(SISCR, 0xb4, 0x02); | ||
5092 | ramtype = reg & 0x01; /* GPIOH */ | ||
5093 | } else if (ivideo->chip == XGI_20) { | ||
5094 | SiS_SetReg(SISCR, 0x97, v1); | ||
5095 | reg = SiS_GetReg(SISCR, 0x97); | ||
5096 | if (reg & 0x10) { | ||
5097 | ramtype = (reg & 0x01) << 1; | ||
5098 | } | ||
5099 | } else { | ||
5100 | reg = SiS_GetReg(SISSR, 0x39); | ||
5101 | ramtype = reg & 0x02; | ||
5102 | if (!(ramtype)) { | ||
5103 | reg = SiS_GetReg(SISSR, 0x3a); | ||
5104 | ramtype = (reg >> 1) & 0x01; | ||
5105 | } | ||
5106 | } | ||
5107 | } | ||
5108 | ramtype &= 0x07; | ||
5109 | |||
5110 | return ramtype; | ||
5111 | } | ||
5112 | |||
4934 | static int __devinit | 5113 | static int __devinit |
4935 | sisfb_post_xgi(struct pci_dev *pdev) | 5114 | sisfb_post_xgi(struct pci_dev *pdev) |
4936 | { | 5115 | { |
@@ -5213,9 +5392,23 @@ sisfb_post_xgi(struct pci_dev *pdev) | |||
5213 | SiS_SetReg(SISCR, 0x77, v1); | 5392 | SiS_SetReg(SISCR, 0x77, v1); |
5214 | } | 5393 | } |
5215 | 5394 | ||
5216 | /* RAM type */ | 5395 | /* RAM type: |
5217 | 5396 | * | |
5218 | regb = 0; /* ! */ | 5397 | * 0 == DDR1, 1 == DDR2, 2..7 == reserved? |
5398 | * | ||
5399 | * The code seems to written so that regb should equal ramtype, | ||
5400 | * however, so far it has been hardcoded to 0. Enable other values only | ||
5401 | * on XGI Z9, as it passes the POST, and add a warning for others. | ||
5402 | */ | ||
5403 | ramtype = sisfb_post_xgi_ramtype(ivideo); | ||
5404 | if (!sisfb_xgi_is21(ivideo) && ramtype) { | ||
5405 | dev_warn(&pdev->dev, | ||
5406 | "RAM type something else than expected: %d\n", | ||
5407 | ramtype); | ||
5408 | regb = 0; | ||
5409 | } else { | ||
5410 | regb = ramtype; | ||
5411 | } | ||
5219 | 5412 | ||
5220 | v1 = 0xff; | 5413 | v1 = 0xff; |
5221 | if(ivideo->haveXGIROM) { | 5414 | if(ivideo->haveXGIROM) { |
@@ -5367,7 +5560,10 @@ sisfb_post_xgi(struct pci_dev *pdev) | |||
5367 | } | 5560 | } |
5368 | } | 5561 | } |
5369 | 5562 | ||
5370 | SiS_SetReg(SISSR, 0x17, 0x00); | 5563 | if (regb == 1) |
5564 | SiS_SetReg(SISSR, 0x17, 0x80); /* DDR2 */ | ||
5565 | else | ||
5566 | SiS_SetReg(SISSR, 0x17, 0x00); /* DDR1 */ | ||
5371 | SiS_SetReg(SISSR, 0x1a, 0x87); | 5567 | SiS_SetReg(SISSR, 0x1a, 0x87); |
5372 | 5568 | ||
5373 | if(ivideo->chip == XGI_20) { | 5569 | if(ivideo->chip == XGI_20) { |
@@ -5375,31 +5571,6 @@ sisfb_post_xgi(struct pci_dev *pdev) | |||
5375 | SiS_SetReg(SISSR, 0x1c, 0x00); | 5571 | SiS_SetReg(SISSR, 0x1c, 0x00); |
5376 | } | 5572 | } |
5377 | 5573 | ||
5378 | ramtype = 0x00; v1 = 0x10; | ||
5379 | if(ivideo->haveXGIROM) { | ||
5380 | ramtype = bios[0x62]; | ||
5381 | v1 = bios[0x1d2]; | ||
5382 | } | ||
5383 | if(!(ramtype & 0x80)) { | ||
5384 | if(ivideo->chip == XGI_20) { | ||
5385 | SiS_SetReg(SISCR, 0x97, v1); | ||
5386 | reg = SiS_GetReg(SISCR, 0x97); | ||
5387 | if(reg & 0x10) { | ||
5388 | ramtype = (reg & 0x01) << 1; | ||
5389 | } | ||
5390 | } else { | ||
5391 | reg = SiS_GetReg(SISSR, 0x39); | ||
5392 | ramtype = reg & 0x02; | ||
5393 | if(!(ramtype)) { | ||
5394 | reg = SiS_GetReg(SISSR, 0x3a); | ||
5395 | ramtype = (reg >> 1) & 0x01; | ||
5396 | } | ||
5397 | } | ||
5398 | } | ||
5399 | ramtype &= 0x07; | ||
5400 | |||
5401 | regb = 0; /* ! */ | ||
5402 | |||
5403 | switch(ramtype) { | 5574 | switch(ramtype) { |
5404 | case 0: | 5575 | case 0: |
5405 | sisfb_post_xgi_setclocks(ivideo, regb); | 5576 | sisfb_post_xgi_setclocks(ivideo, regb); |
@@ -5485,61 +5656,7 @@ sisfb_post_xgi(struct pci_dev *pdev) | |||
5485 | SiS_SetReg(SISSR, 0x1b, 0x00); | 5656 | SiS_SetReg(SISSR, 0x1b, 0x00); |
5486 | break; | 5657 | break; |
5487 | case 1: | 5658 | case 1: |
5488 | SiS_SetReg(SISCR, 0x82, 0x77); | 5659 | sisfb_post_xgi_ddr2(ivideo, regb); |
5489 | SiS_SetReg(SISCR, 0x86, 0x00); | ||
5490 | reg = SiS_GetReg(SISCR, 0x86); | ||
5491 | SiS_SetReg(SISCR, 0x86, 0x88); | ||
5492 | reg = SiS_GetReg(SISCR, 0x86); | ||
5493 | v1 = cs168[regb]; v2 = cs160[regb]; v3 = cs158[regb]; | ||
5494 | if(ivideo->haveXGIROM) { | ||
5495 | v1 = bios[regb + 0x168]; | ||
5496 | v2 = bios[regb + 0x160]; | ||
5497 | v3 = bios[regb + 0x158]; | ||
5498 | } | ||
5499 | SiS_SetReg(SISCR, 0x86, v1); | ||
5500 | SiS_SetReg(SISCR, 0x82, 0x77); | ||
5501 | SiS_SetReg(SISCR, 0x85, 0x00); | ||
5502 | reg = SiS_GetReg(SISCR, 0x85); | ||
5503 | SiS_SetReg(SISCR, 0x85, 0x88); | ||
5504 | reg = SiS_GetReg(SISCR, 0x85); | ||
5505 | SiS_SetReg(SISCR, 0x85, v2); | ||
5506 | SiS_SetReg(SISCR, 0x82, v3); | ||
5507 | SiS_SetReg(SISCR, 0x98, 0x01); | ||
5508 | SiS_SetReg(SISCR, 0x9a, 0x02); | ||
5509 | |||
5510 | SiS_SetReg(SISSR, 0x28, 0x64); | ||
5511 | SiS_SetReg(SISSR, 0x29, 0x63); | ||
5512 | sisfb_post_xgi_delay(ivideo, 15); | ||
5513 | SiS_SetReg(SISSR, 0x18, 0x00); | ||
5514 | SiS_SetReg(SISSR, 0x19, 0x20); | ||
5515 | SiS_SetReg(SISSR, 0x16, 0x00); | ||
5516 | SiS_SetReg(SISSR, 0x16, 0x80); | ||
5517 | SiS_SetReg(SISSR, 0x18, 0xc5); | ||
5518 | SiS_SetReg(SISSR, 0x19, 0x23); | ||
5519 | SiS_SetReg(SISSR, 0x16, 0x00); | ||
5520 | SiS_SetReg(SISSR, 0x16, 0x80); | ||
5521 | sisfb_post_xgi_delay(ivideo, 1); | ||
5522 | SiS_SetReg(SISCR, 0x97, 0x11); | ||
5523 | sisfb_post_xgi_setclocks(ivideo, regb); | ||
5524 | sisfb_post_xgi_delay(ivideo, 0x46); | ||
5525 | SiS_SetReg(SISSR, 0x18, 0xc5); | ||
5526 | SiS_SetReg(SISSR, 0x19, 0x23); | ||
5527 | SiS_SetReg(SISSR, 0x16, 0x00); | ||
5528 | SiS_SetReg(SISSR, 0x16, 0x80); | ||
5529 | sisfb_post_xgi_delay(ivideo, 1); | ||
5530 | SiS_SetReg(SISSR, 0x1b, 0x04); | ||
5531 | sisfb_post_xgi_delay(ivideo, 1); | ||
5532 | SiS_SetReg(SISSR, 0x1b, 0x00); | ||
5533 | sisfb_post_xgi_delay(ivideo, 1); | ||
5534 | v1 = 0x31; | ||
5535 | if(ivideo->haveXGIROM) { | ||
5536 | v1 = bios[0xf0]; | ||
5537 | } | ||
5538 | SiS_SetReg(SISSR, 0x18, v1); | ||
5539 | SiS_SetReg(SISSR, 0x19, 0x06); | ||
5540 | SiS_SetReg(SISSR, 0x16, 0x04); | ||
5541 | SiS_SetReg(SISSR, 0x16, 0x84); | ||
5542 | sisfb_post_xgi_delay(ivideo, 1); | ||
5543 | break; | 5660 | break; |
5544 | default: | 5661 | default: |
5545 | sisfb_post_xgi_setclocks(ivideo, regb); | 5662 | sisfb_post_xgi_setclocks(ivideo, regb); |
@@ -5648,6 +5765,7 @@ sisfb_post_xgi(struct pci_dev *pdev) | |||
5648 | SiS_SetReg(SISSR, 0x14, bios[regb + 0xe0 + 8]); | 5765 | SiS_SetReg(SISSR, 0x14, bios[regb + 0xe0 + 8]); |
5649 | 5766 | ||
5650 | } else { | 5767 | } else { |
5768 | int err; | ||
5651 | 5769 | ||
5652 | /* Set default mode, don't clear screen */ | 5770 | /* Set default mode, don't clear screen */ |
5653 | ivideo->SiS_Pr.SiS_UseOEM = false; | 5771 | ivideo->SiS_Pr.SiS_UseOEM = false; |
@@ -5661,10 +5779,16 @@ sisfb_post_xgi(struct pci_dev *pdev) | |||
5661 | 5779 | ||
5662 | /* Disable read-cache */ | 5780 | /* Disable read-cache */ |
5663 | SiS_SetRegAND(SISSR, 0x21, 0xdf); | 5781 | SiS_SetRegAND(SISSR, 0x21, 0xdf); |
5664 | sisfb_post_xgi_ramsize(ivideo); | 5782 | err = sisfb_post_xgi_ramsize(ivideo); |
5665 | /* Enable read-cache */ | 5783 | /* Enable read-cache */ |
5666 | SiS_SetRegOR(SISSR, 0x21, 0x20); | 5784 | SiS_SetRegOR(SISSR, 0x21, 0x20); |
5667 | 5785 | ||
5786 | if (err) { | ||
5787 | dev_err(&pdev->dev, | ||
5788 | "%s: RAM size detection failed: %d\n", | ||
5789 | __func__, err); | ||
5790 | return 0; | ||
5791 | } | ||
5668 | } | 5792 | } |
5669 | 5793 | ||
5670 | #if 0 | 5794 | #if 0 |
@@ -5777,6 +5901,7 @@ sisfb_probe(struct pci_dev *pdev, const struct pci_device_id *ent) | |||
5777 | #endif | 5901 | #endif |
5778 | 5902 | ||
5779 | ivideo->chip = chipinfo->chip; | 5903 | ivideo->chip = chipinfo->chip; |
5904 | ivideo->chip_real_id = chipinfo->chip; | ||
5780 | ivideo->sisvga_engine = chipinfo->vgaengine; | 5905 | ivideo->sisvga_engine = chipinfo->vgaengine; |
5781 | ivideo->hwcursor_size = chipinfo->hwcursor_size; | 5906 | ivideo->hwcursor_size = chipinfo->hwcursor_size; |
5782 | ivideo->CRT2_write_enable = chipinfo->CRT2_write_enable; | 5907 | ivideo->CRT2_write_enable = chipinfo->CRT2_write_enable; |
@@ -6010,6 +6135,18 @@ sisfb_probe(struct pci_dev *pdev, const struct pci_device_id *ent) | |||
6010 | sisfb_detect_custom_timing(ivideo); | 6135 | sisfb_detect_custom_timing(ivideo); |
6011 | } | 6136 | } |
6012 | 6137 | ||
6138 | #ifdef CONFIG_FB_SIS_315 | ||
6139 | if (ivideo->chip == XGI_20) { | ||
6140 | /* Check if our Z7 chip is actually Z9 */ | ||
6141 | SiS_SetRegOR(SISCR, 0x4a, 0x40); /* GPIOG EN */ | ||
6142 | reg = SiS_GetReg(SISCR, 0x48); | ||
6143 | if (reg & 0x02) { /* GPIOG */ | ||
6144 | ivideo->chip_real_id = XGI_21; | ||
6145 | dev_info(&pdev->dev, "Z9 detected\n"); | ||
6146 | } | ||
6147 | } | ||
6148 | #endif | ||
6149 | |||
6013 | /* POST card in case this has not been done by the BIOS */ | 6150 | /* POST card in case this has not been done by the BIOS */ |
6014 | if( (!ivideo->sisvga_enabled) | 6151 | if( (!ivideo->sisvga_enabled) |
6015 | #if !defined(__i386__) && !defined(__x86_64__) | 6152 | #if !defined(__i386__) && !defined(__x86_64__) |
diff --git a/drivers/video/sis/vgatypes.h b/drivers/video/sis/vgatypes.h index 12c0dfaf2518..e3f9976cfef0 100644 --- a/drivers/video/sis/vgatypes.h +++ b/drivers/video/sis/vgatypes.h | |||
@@ -87,6 +87,7 @@ typedef enum _SIS_CHIP_TYPE { | |||
87 | SIS_341, | 87 | SIS_341, |
88 | SIS_342, | 88 | SIS_342, |
89 | XGI_20 = 75, | 89 | XGI_20 = 75, |
90 | XGI_21, | ||
90 | XGI_40, | 91 | XGI_40, |
91 | MAX_SIS_CHIP | 92 | MAX_SIS_CHIP |
92 | } SIS_CHIP_TYPE; | 93 | } SIS_CHIP_TYPE; |
diff --git a/drivers/video/sm501fb.c b/drivers/video/sm501fb.c index bcb44a594ebc..46d1a64fe80d 100644 --- a/drivers/video/sm501fb.c +++ b/drivers/video/sm501fb.c | |||
@@ -41,6 +41,26 @@ | |||
41 | #include <linux/sm501.h> | 41 | #include <linux/sm501.h> |
42 | #include <linux/sm501-regs.h> | 42 | #include <linux/sm501-regs.h> |
43 | 43 | ||
44 | #include "edid.h" | ||
45 | |||
46 | static char *fb_mode = "640x480-16@60"; | ||
47 | static unsigned long default_bpp = 16; | ||
48 | |||
49 | static struct fb_videomode __devinitdata sm501_default_mode = { | ||
50 | .refresh = 60, | ||
51 | .xres = 640, | ||
52 | .yres = 480, | ||
53 | .pixclock = 20833, | ||
54 | .left_margin = 142, | ||
55 | .right_margin = 13, | ||
56 | .upper_margin = 21, | ||
57 | .lower_margin = 1, | ||
58 | .hsync_len = 69, | ||
59 | .vsync_len = 3, | ||
60 | .sync = FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT, | ||
61 | .vmode = FB_VMODE_NONINTERLACED | ||
62 | }; | ||
63 | |||
44 | #define NR_PALETTE 256 | 64 | #define NR_PALETTE 256 |
45 | 65 | ||
46 | enum sm501_controller { | 66 | enum sm501_controller { |
@@ -77,6 +97,7 @@ struct sm501fb_info { | |||
77 | void __iomem *regs2d; /* 2d remapped registers */ | 97 | void __iomem *regs2d; /* 2d remapped registers */ |
78 | void __iomem *fbmem; /* remapped framebuffer */ | 98 | void __iomem *fbmem; /* remapped framebuffer */ |
79 | size_t fbmem_len; /* length of remapped region */ | 99 | size_t fbmem_len; /* length of remapped region */ |
100 | u8 *edid_data; | ||
80 | }; | 101 | }; |
81 | 102 | ||
82 | /* per-framebuffer private data */ | 103 | /* per-framebuffer private data */ |
@@ -117,7 +138,7 @@ static inline int v_total(struct fb_var_screeninfo *var) | |||
117 | 138 | ||
118 | static inline void sm501fb_sync_regs(struct sm501fb_info *info) | 139 | static inline void sm501fb_sync_regs(struct sm501fb_info *info) |
119 | { | 140 | { |
120 | readl(info->regs); | 141 | smc501_readl(info->regs); |
121 | } | 142 | } |
122 | 143 | ||
123 | /* sm501_alloc_mem | 144 | /* sm501_alloc_mem |
@@ -262,7 +283,7 @@ static void sm501fb_setup_gamma(struct sm501fb_info *fbi, | |||
262 | 283 | ||
263 | /* set gamma values */ | 284 | /* set gamma values */ |
264 | for (offset = 0; offset < 256 * 4; offset += 4) { | 285 | for (offset = 0; offset < 256 * 4; offset += 4) { |
265 | writel(value, fbi->regs + palette + offset); | 286 | smc501_writel(value, fbi->regs + palette + offset); |
266 | value += 0x010101; /* Advance RGB by 1,1,1.*/ | 287 | value += 0x010101; /* Advance RGB by 1,1,1.*/ |
267 | } | 288 | } |
268 | } | 289 | } |
@@ -476,7 +497,8 @@ static int sm501fb_set_par_common(struct fb_info *info, | |||
476 | 497 | ||
477 | /* set start of framebuffer to the screen */ | 498 | /* set start of framebuffer to the screen */ |
478 | 499 | ||
479 | writel(par->screen.sm_addr | SM501_ADDR_FLIP, fbi->regs + head_addr); | 500 | smc501_writel(par->screen.sm_addr | SM501_ADDR_FLIP, |
501 | fbi->regs + head_addr); | ||
480 | 502 | ||
481 | /* program CRT clock */ | 503 | /* program CRT clock */ |
482 | 504 | ||
@@ -519,7 +541,7 @@ static void sm501fb_set_par_geometry(struct fb_info *info, | |||
519 | reg = info->fix.line_length; | 541 | reg = info->fix.line_length; |
520 | reg |= ((var->xres * var->bits_per_pixel)/8) << 16; | 542 | reg |= ((var->xres * var->bits_per_pixel)/8) << 16; |
521 | 543 | ||
522 | writel(reg, fbi->regs + (par->head == HEAD_CRT ? | 544 | smc501_writel(reg, fbi->regs + (par->head == HEAD_CRT ? |
523 | SM501_DC_CRT_FB_OFFSET : SM501_DC_PANEL_FB_OFFSET)); | 545 | SM501_DC_CRT_FB_OFFSET : SM501_DC_PANEL_FB_OFFSET)); |
524 | 546 | ||
525 | /* program horizontal total */ | 547 | /* program horizontal total */ |
@@ -527,27 +549,27 @@ static void sm501fb_set_par_geometry(struct fb_info *info, | |||
527 | reg = (h_total(var) - 1) << 16; | 549 | reg = (h_total(var) - 1) << 16; |
528 | reg |= (var->xres - 1); | 550 | reg |= (var->xres - 1); |
529 | 551 | ||
530 | writel(reg, base + SM501_OFF_DC_H_TOT); | 552 | smc501_writel(reg, base + SM501_OFF_DC_H_TOT); |
531 | 553 | ||
532 | /* program horizontal sync */ | 554 | /* program horizontal sync */ |
533 | 555 | ||
534 | reg = var->hsync_len << 16; | 556 | reg = var->hsync_len << 16; |
535 | reg |= var->xres + var->right_margin - 1; | 557 | reg |= var->xres + var->right_margin - 1; |
536 | 558 | ||
537 | writel(reg, base + SM501_OFF_DC_H_SYNC); | 559 | smc501_writel(reg, base + SM501_OFF_DC_H_SYNC); |
538 | 560 | ||
539 | /* program vertical total */ | 561 | /* program vertical total */ |
540 | 562 | ||
541 | reg = (v_total(var) - 1) << 16; | 563 | reg = (v_total(var) - 1) << 16; |
542 | reg |= (var->yres - 1); | 564 | reg |= (var->yres - 1); |
543 | 565 | ||
544 | writel(reg, base + SM501_OFF_DC_V_TOT); | 566 | smc501_writel(reg, base + SM501_OFF_DC_V_TOT); |
545 | 567 | ||
546 | /* program vertical sync */ | 568 | /* program vertical sync */ |
547 | reg = var->vsync_len << 16; | 569 | reg = var->vsync_len << 16; |
548 | reg |= var->yres + var->lower_margin - 1; | 570 | reg |= var->yres + var->lower_margin - 1; |
549 | 571 | ||
550 | writel(reg, base + SM501_OFF_DC_V_SYNC); | 572 | smc501_writel(reg, base + SM501_OFF_DC_V_SYNC); |
551 | } | 573 | } |
552 | 574 | ||
553 | /* sm501fb_pan_crt | 575 | /* sm501fb_pan_crt |
@@ -566,15 +588,15 @@ static int sm501fb_pan_crt(struct fb_var_screeninfo *var, | |||
566 | 588 | ||
567 | xoffs = var->xoffset * bytes_pixel; | 589 | xoffs = var->xoffset * bytes_pixel; |
568 | 590 | ||
569 | reg = readl(fbi->regs + SM501_DC_CRT_CONTROL); | 591 | reg = smc501_readl(fbi->regs + SM501_DC_CRT_CONTROL); |
570 | 592 | ||
571 | reg &= ~SM501_DC_CRT_CONTROL_PIXEL_MASK; | 593 | reg &= ~SM501_DC_CRT_CONTROL_PIXEL_MASK; |
572 | reg |= ((xoffs & 15) / bytes_pixel) << 4; | 594 | reg |= ((xoffs & 15) / bytes_pixel) << 4; |
573 | writel(reg, fbi->regs + SM501_DC_CRT_CONTROL); | 595 | smc501_writel(reg, fbi->regs + SM501_DC_CRT_CONTROL); |
574 | 596 | ||
575 | reg = (par->screen.sm_addr + xoffs + | 597 | reg = (par->screen.sm_addr + xoffs + |
576 | var->yoffset * info->fix.line_length); | 598 | var->yoffset * info->fix.line_length); |
577 | writel(reg | SM501_ADDR_FLIP, fbi->regs + SM501_DC_CRT_FB_ADDR); | 599 | smc501_writel(reg | SM501_ADDR_FLIP, fbi->regs + SM501_DC_CRT_FB_ADDR); |
578 | 600 | ||
579 | sm501fb_sync_regs(fbi); | 601 | sm501fb_sync_regs(fbi); |
580 | return 0; | 602 | return 0; |
@@ -593,10 +615,10 @@ static int sm501fb_pan_pnl(struct fb_var_screeninfo *var, | |||
593 | unsigned long reg; | 615 | unsigned long reg; |
594 | 616 | ||
595 | reg = var->xoffset | (var->xres_virtual << 16); | 617 | reg = var->xoffset | (var->xres_virtual << 16); |
596 | writel(reg, fbi->regs + SM501_DC_PANEL_FB_WIDTH); | 618 | smc501_writel(reg, fbi->regs + SM501_DC_PANEL_FB_WIDTH); |
597 | 619 | ||
598 | reg = var->yoffset | (var->yres_virtual << 16); | 620 | reg = var->yoffset | (var->yres_virtual << 16); |
599 | writel(reg, fbi->regs + SM501_DC_PANEL_FB_HEIGHT); | 621 | smc501_writel(reg, fbi->regs + SM501_DC_PANEL_FB_HEIGHT); |
600 | 622 | ||
601 | sm501fb_sync_regs(fbi); | 623 | sm501fb_sync_regs(fbi); |
602 | return 0; | 624 | return 0; |
@@ -622,7 +644,7 @@ static int sm501fb_set_par_crt(struct fb_info *info) | |||
622 | /* enable CRT DAC - note 0 is on!*/ | 644 | /* enable CRT DAC - note 0 is on!*/ |
623 | sm501_misc_control(fbi->dev->parent, 0, SM501_MISC_DAC_POWER); | 645 | sm501_misc_control(fbi->dev->parent, 0, SM501_MISC_DAC_POWER); |
624 | 646 | ||
625 | control = readl(fbi->regs + SM501_DC_CRT_CONTROL); | 647 | control = smc501_readl(fbi->regs + SM501_DC_CRT_CONTROL); |
626 | 648 | ||
627 | control &= (SM501_DC_CRT_CONTROL_PIXEL_MASK | | 649 | control &= (SM501_DC_CRT_CONTROL_PIXEL_MASK | |
628 | SM501_DC_CRT_CONTROL_GAMMA | | 650 | SM501_DC_CRT_CONTROL_GAMMA | |
@@ -684,7 +706,7 @@ static int sm501fb_set_par_crt(struct fb_info *info) | |||
684 | out_update: | 706 | out_update: |
685 | dev_dbg(fbi->dev, "new control is %08lx\n", control); | 707 | dev_dbg(fbi->dev, "new control is %08lx\n", control); |
686 | 708 | ||
687 | writel(control, fbi->regs + SM501_DC_CRT_CONTROL); | 709 | smc501_writel(control, fbi->regs + SM501_DC_CRT_CONTROL); |
688 | sm501fb_sync_regs(fbi); | 710 | sm501fb_sync_regs(fbi); |
689 | 711 | ||
690 | return 0; | 712 | return 0; |
@@ -696,18 +718,18 @@ static void sm501fb_panel_power(struct sm501fb_info *fbi, int to) | |||
696 | void __iomem *ctrl_reg = fbi->regs + SM501_DC_PANEL_CONTROL; | 718 | void __iomem *ctrl_reg = fbi->regs + SM501_DC_PANEL_CONTROL; |
697 | struct sm501_platdata_fbsub *pd = fbi->pdata->fb_pnl; | 719 | struct sm501_platdata_fbsub *pd = fbi->pdata->fb_pnl; |
698 | 720 | ||
699 | control = readl(ctrl_reg); | 721 | control = smc501_readl(ctrl_reg); |
700 | 722 | ||
701 | if (to && (control & SM501_DC_PANEL_CONTROL_VDD) == 0) { | 723 | if (to && (control & SM501_DC_PANEL_CONTROL_VDD) == 0) { |
702 | /* enable panel power */ | 724 | /* enable panel power */ |
703 | 725 | ||
704 | control |= SM501_DC_PANEL_CONTROL_VDD; /* FPVDDEN */ | 726 | control |= SM501_DC_PANEL_CONTROL_VDD; /* FPVDDEN */ |
705 | writel(control, ctrl_reg); | 727 | smc501_writel(control, ctrl_reg); |
706 | sm501fb_sync_regs(fbi); | 728 | sm501fb_sync_regs(fbi); |
707 | mdelay(10); | 729 | mdelay(10); |
708 | 730 | ||
709 | control |= SM501_DC_PANEL_CONTROL_DATA; /* DATA */ | 731 | control |= SM501_DC_PANEL_CONTROL_DATA; /* DATA */ |
710 | writel(control, ctrl_reg); | 732 | smc501_writel(control, ctrl_reg); |
711 | sm501fb_sync_regs(fbi); | 733 | sm501fb_sync_regs(fbi); |
712 | mdelay(10); | 734 | mdelay(10); |
713 | 735 | ||
@@ -719,7 +741,7 @@ static void sm501fb_panel_power(struct sm501fb_info *fbi, int to) | |||
719 | else | 741 | else |
720 | control |= SM501_DC_PANEL_CONTROL_BIAS; | 742 | control |= SM501_DC_PANEL_CONTROL_BIAS; |
721 | 743 | ||
722 | writel(control, ctrl_reg); | 744 | smc501_writel(control, ctrl_reg); |
723 | sm501fb_sync_regs(fbi); | 745 | sm501fb_sync_regs(fbi); |
724 | mdelay(10); | 746 | mdelay(10); |
725 | } | 747 | } |
@@ -730,7 +752,7 @@ static void sm501fb_panel_power(struct sm501fb_info *fbi, int to) | |||
730 | else | 752 | else |
731 | control |= SM501_DC_PANEL_CONTROL_FPEN; | 753 | control |= SM501_DC_PANEL_CONTROL_FPEN; |
732 | 754 | ||
733 | writel(control, ctrl_reg); | 755 | smc501_writel(control, ctrl_reg); |
734 | sm501fb_sync_regs(fbi); | 756 | sm501fb_sync_regs(fbi); |
735 | mdelay(10); | 757 | mdelay(10); |
736 | } | 758 | } |
@@ -742,7 +764,7 @@ static void sm501fb_panel_power(struct sm501fb_info *fbi, int to) | |||
742 | else | 764 | else |
743 | control &= ~SM501_DC_PANEL_CONTROL_FPEN; | 765 | control &= ~SM501_DC_PANEL_CONTROL_FPEN; |
744 | 766 | ||
745 | writel(control, ctrl_reg); | 767 | smc501_writel(control, ctrl_reg); |
746 | sm501fb_sync_regs(fbi); | 768 | sm501fb_sync_regs(fbi); |
747 | mdelay(10); | 769 | mdelay(10); |
748 | } | 770 | } |
@@ -753,18 +775,18 @@ static void sm501fb_panel_power(struct sm501fb_info *fbi, int to) | |||
753 | else | 775 | else |
754 | control &= ~SM501_DC_PANEL_CONTROL_BIAS; | 776 | control &= ~SM501_DC_PANEL_CONTROL_BIAS; |
755 | 777 | ||
756 | writel(control, ctrl_reg); | 778 | smc501_writel(control, ctrl_reg); |
757 | sm501fb_sync_regs(fbi); | 779 | sm501fb_sync_regs(fbi); |
758 | mdelay(10); | 780 | mdelay(10); |
759 | } | 781 | } |
760 | 782 | ||
761 | control &= ~SM501_DC_PANEL_CONTROL_DATA; | 783 | control &= ~SM501_DC_PANEL_CONTROL_DATA; |
762 | writel(control, ctrl_reg); | 784 | smc501_writel(control, ctrl_reg); |
763 | sm501fb_sync_regs(fbi); | 785 | sm501fb_sync_regs(fbi); |
764 | mdelay(10); | 786 | mdelay(10); |
765 | 787 | ||
766 | control &= ~SM501_DC_PANEL_CONTROL_VDD; | 788 | control &= ~SM501_DC_PANEL_CONTROL_VDD; |
767 | writel(control, ctrl_reg); | 789 | smc501_writel(control, ctrl_reg); |
768 | sm501fb_sync_regs(fbi); | 790 | sm501fb_sync_regs(fbi); |
769 | mdelay(10); | 791 | mdelay(10); |
770 | } | 792 | } |
@@ -799,7 +821,7 @@ static int sm501fb_set_par_pnl(struct fb_info *info) | |||
799 | 821 | ||
800 | /* update control register */ | 822 | /* update control register */ |
801 | 823 | ||
802 | control = readl(fbi->regs + SM501_DC_PANEL_CONTROL); | 824 | control = smc501_readl(fbi->regs + SM501_DC_PANEL_CONTROL); |
803 | control &= (SM501_DC_PANEL_CONTROL_GAMMA | | 825 | control &= (SM501_DC_PANEL_CONTROL_GAMMA | |
804 | SM501_DC_PANEL_CONTROL_VDD | | 826 | SM501_DC_PANEL_CONTROL_VDD | |
805 | SM501_DC_PANEL_CONTROL_DATA | | 827 | SM501_DC_PANEL_CONTROL_DATA | |
@@ -833,16 +855,16 @@ static int sm501fb_set_par_pnl(struct fb_info *info) | |||
833 | BUG(); | 855 | BUG(); |
834 | } | 856 | } |
835 | 857 | ||
836 | writel(0x0, fbi->regs + SM501_DC_PANEL_PANNING_CONTROL); | 858 | smc501_writel(0x0, fbi->regs + SM501_DC_PANEL_PANNING_CONTROL); |
837 | 859 | ||
838 | /* panel plane top left and bottom right location */ | 860 | /* panel plane top left and bottom right location */ |
839 | 861 | ||
840 | writel(0x00, fbi->regs + SM501_DC_PANEL_TL_LOC); | 862 | smc501_writel(0x00, fbi->regs + SM501_DC_PANEL_TL_LOC); |
841 | 863 | ||
842 | reg = var->xres - 1; | 864 | reg = var->xres - 1; |
843 | reg |= (var->yres - 1) << 16; | 865 | reg |= (var->yres - 1) << 16; |
844 | 866 | ||
845 | writel(reg, fbi->regs + SM501_DC_PANEL_BR_LOC); | 867 | smc501_writel(reg, fbi->regs + SM501_DC_PANEL_BR_LOC); |
846 | 868 | ||
847 | /* program panel control register */ | 869 | /* program panel control register */ |
848 | 870 | ||
@@ -855,7 +877,7 @@ static int sm501fb_set_par_pnl(struct fb_info *info) | |||
855 | if ((var->sync & FB_SYNC_VERT_HIGH_ACT) == 0) | 877 | if ((var->sync & FB_SYNC_VERT_HIGH_ACT) == 0) |
856 | control |= SM501_DC_PANEL_CONTROL_VSP; | 878 | control |= SM501_DC_PANEL_CONTROL_VSP; |
857 | 879 | ||
858 | writel(control, fbi->regs + SM501_DC_PANEL_CONTROL); | 880 | smc501_writel(control, fbi->regs + SM501_DC_PANEL_CONTROL); |
859 | sm501fb_sync_regs(fbi); | 881 | sm501fb_sync_regs(fbi); |
860 | 882 | ||
861 | /* ensure the panel interface is not tristated at this point */ | 883 | /* ensure the panel interface is not tristated at this point */ |
@@ -924,7 +946,7 @@ static int sm501fb_setcolreg(unsigned regno, | |||
924 | val |= (green >> 8) << 8; | 946 | val |= (green >> 8) << 8; |
925 | val |= blue >> 8; | 947 | val |= blue >> 8; |
926 | 948 | ||
927 | writel(val, base + (regno * 4)); | 949 | smc501_writel(val, base + (regno * 4)); |
928 | } | 950 | } |
929 | 951 | ||
930 | break; | 952 | break; |
@@ -980,7 +1002,7 @@ static int sm501fb_blank_crt(int blank_mode, struct fb_info *info) | |||
980 | 1002 | ||
981 | dev_dbg(fbi->dev, "%s(mode=%d, %p)\n", __func__, blank_mode, info); | 1003 | dev_dbg(fbi->dev, "%s(mode=%d, %p)\n", __func__, blank_mode, info); |
982 | 1004 | ||
983 | ctrl = readl(fbi->regs + SM501_DC_CRT_CONTROL); | 1005 | ctrl = smc501_readl(fbi->regs + SM501_DC_CRT_CONTROL); |
984 | 1006 | ||
985 | switch (blank_mode) { | 1007 | switch (blank_mode) { |
986 | case FB_BLANK_POWERDOWN: | 1008 | case FB_BLANK_POWERDOWN: |
@@ -1004,7 +1026,7 @@ static int sm501fb_blank_crt(int blank_mode, struct fb_info *info) | |||
1004 | 1026 | ||
1005 | } | 1027 | } |
1006 | 1028 | ||
1007 | writel(ctrl, fbi->regs + SM501_DC_CRT_CONTROL); | 1029 | smc501_writel(ctrl, fbi->regs + SM501_DC_CRT_CONTROL); |
1008 | sm501fb_sync_regs(fbi); | 1030 | sm501fb_sync_regs(fbi); |
1009 | 1031 | ||
1010 | return 0; | 1032 | return 0; |
@@ -1041,12 +1063,14 @@ static int sm501fb_cursor(struct fb_info *info, struct fb_cursor *cursor) | |||
1041 | if (cursor->image.depth > 1) | 1063 | if (cursor->image.depth > 1) |
1042 | return -EINVAL; | 1064 | return -EINVAL; |
1043 | 1065 | ||
1044 | hwc_addr = readl(base + SM501_OFF_HWC_ADDR); | 1066 | hwc_addr = smc501_readl(base + SM501_OFF_HWC_ADDR); |
1045 | 1067 | ||
1046 | if (cursor->enable) | 1068 | if (cursor->enable) |
1047 | writel(hwc_addr | SM501_HWC_EN, base + SM501_OFF_HWC_ADDR); | 1069 | smc501_writel(hwc_addr | SM501_HWC_EN, |
1070 | base + SM501_OFF_HWC_ADDR); | ||
1048 | else | 1071 | else |
1049 | writel(hwc_addr & ~SM501_HWC_EN, base + SM501_OFF_HWC_ADDR); | 1072 | smc501_writel(hwc_addr & ~SM501_HWC_EN, |
1073 | base + SM501_OFF_HWC_ADDR); | ||
1050 | 1074 | ||
1051 | /* set data */ | 1075 | /* set data */ |
1052 | if (cursor->set & FB_CUR_SETPOS) { | 1076 | if (cursor->set & FB_CUR_SETPOS) { |
@@ -1060,7 +1084,7 @@ static int sm501fb_cursor(struct fb_info *info, struct fb_cursor *cursor) | |||
1060 | 1084 | ||
1061 | //y += cursor->image.height; | 1085 | //y += cursor->image.height; |
1062 | 1086 | ||
1063 | writel(x | (y << 16), base + SM501_OFF_HWC_LOC); | 1087 | smc501_writel(x | (y << 16), base + SM501_OFF_HWC_LOC); |
1064 | } | 1088 | } |
1065 | 1089 | ||
1066 | if (cursor->set & FB_CUR_SETCMAP) { | 1090 | if (cursor->set & FB_CUR_SETCMAP) { |
@@ -1080,8 +1104,8 @@ static int sm501fb_cursor(struct fb_info *info, struct fb_cursor *cursor) | |||
1080 | 1104 | ||
1081 | dev_dbg(fbi->dev, "fgcol %08lx, bgcol %08lx\n", fg, bg); | 1105 | dev_dbg(fbi->dev, "fgcol %08lx, bgcol %08lx\n", fg, bg); |
1082 | 1106 | ||
1083 | writel(bg, base + SM501_OFF_HWC_COLOR_1_2); | 1107 | smc501_writel(bg, base + SM501_OFF_HWC_COLOR_1_2); |
1084 | writel(fg, base + SM501_OFF_HWC_COLOR_3); | 1108 | smc501_writel(fg, base + SM501_OFF_HWC_COLOR_3); |
1085 | } | 1109 | } |
1086 | 1110 | ||
1087 | if (cursor->set & FB_CUR_SETSIZE || | 1111 | if (cursor->set & FB_CUR_SETSIZE || |
@@ -1102,7 +1126,7 @@ static int sm501fb_cursor(struct fb_info *info, struct fb_cursor *cursor) | |||
1102 | __func__, cursor->image.width, cursor->image.height); | 1126 | __func__, cursor->image.width, cursor->image.height); |
1103 | 1127 | ||
1104 | for (op = 0; op < (64*64*2)/8; op+=4) | 1128 | for (op = 0; op < (64*64*2)/8; op+=4) |
1105 | writel(0x0, dst + op); | 1129 | smc501_writel(0x0, dst + op); |
1106 | 1130 | ||
1107 | for (y = 0; y < cursor->image.height; y++) { | 1131 | for (y = 0; y < cursor->image.height; y++) { |
1108 | for (x = 0; x < cursor->image.width; x++) { | 1132 | for (x = 0; x < cursor->image.width; x++) { |
@@ -1141,7 +1165,7 @@ static ssize_t sm501fb_crtsrc_show(struct device *dev, | |||
1141 | struct sm501fb_info *info = dev_get_drvdata(dev); | 1165 | struct sm501fb_info *info = dev_get_drvdata(dev); |
1142 | unsigned long ctrl; | 1166 | unsigned long ctrl; |
1143 | 1167 | ||
1144 | ctrl = readl(info->regs + SM501_DC_CRT_CONTROL); | 1168 | ctrl = smc501_readl(info->regs + SM501_DC_CRT_CONTROL); |
1145 | ctrl &= SM501_DC_CRT_CONTROL_SEL; | 1169 | ctrl &= SM501_DC_CRT_CONTROL_SEL; |
1146 | 1170 | ||
1147 | return snprintf(buf, PAGE_SIZE, "%s\n", ctrl ? "crt" : "panel"); | 1171 | return snprintf(buf, PAGE_SIZE, "%s\n", ctrl ? "crt" : "panel"); |
@@ -1172,7 +1196,7 @@ static ssize_t sm501fb_crtsrc_store(struct device *dev, | |||
1172 | 1196 | ||
1173 | dev_info(dev, "setting crt source to head %d\n", head); | 1197 | dev_info(dev, "setting crt source to head %d\n", head); |
1174 | 1198 | ||
1175 | ctrl = readl(info->regs + SM501_DC_CRT_CONTROL); | 1199 | ctrl = smc501_readl(info->regs + SM501_DC_CRT_CONTROL); |
1176 | 1200 | ||
1177 | if (head == HEAD_CRT) { | 1201 | if (head == HEAD_CRT) { |
1178 | ctrl |= SM501_DC_CRT_CONTROL_SEL; | 1202 | ctrl |= SM501_DC_CRT_CONTROL_SEL; |
@@ -1184,7 +1208,7 @@ static ssize_t sm501fb_crtsrc_store(struct device *dev, | |||
1184 | ctrl &= ~SM501_DC_CRT_CONTROL_TE; | 1208 | ctrl &= ~SM501_DC_CRT_CONTROL_TE; |
1185 | } | 1209 | } |
1186 | 1210 | ||
1187 | writel(ctrl, info->regs + SM501_DC_CRT_CONTROL); | 1211 | smc501_writel(ctrl, info->regs + SM501_DC_CRT_CONTROL); |
1188 | sm501fb_sync_regs(info); | 1212 | sm501fb_sync_regs(info); |
1189 | 1213 | ||
1190 | return len; | 1214 | return len; |
@@ -1205,7 +1229,8 @@ static int sm501fb_show_regs(struct sm501fb_info *info, char *ptr, | |||
1205 | unsigned int reg; | 1229 | unsigned int reg; |
1206 | 1230 | ||
1207 | for (reg = start; reg < (len + start); reg += 4) | 1231 | for (reg = start; reg < (len + start); reg += 4) |
1208 | ptr += sprintf(ptr, "%08x = %08x\n", reg, readl(mem + reg)); | 1232 | ptr += sprintf(ptr, "%08x = %08x\n", reg, |
1233 | smc501_readl(mem + reg)); | ||
1209 | 1234 | ||
1210 | return ptr - buf; | 1235 | return ptr - buf; |
1211 | } | 1236 | } |
@@ -1257,7 +1282,7 @@ static int sm501fb_sync(struct fb_info *info) | |||
1257 | 1282 | ||
1258 | /* wait for the 2d engine to be ready */ | 1283 | /* wait for the 2d engine to be ready */ |
1259 | while ((count > 0) && | 1284 | while ((count > 0) && |
1260 | (readl(fbi->regs + SM501_SYSTEM_CONTROL) & | 1285 | (smc501_readl(fbi->regs + SM501_SYSTEM_CONTROL) & |
1261 | SM501_SYSCTRL_2D_ENGINE_STATUS) != 0) | 1286 | SM501_SYSCTRL_2D_ENGINE_STATUS) != 0) |
1262 | count--; | 1287 | count--; |
1263 | 1288 | ||
@@ -1312,45 +1337,46 @@ static void sm501fb_copyarea(struct fb_info *info, const struct fb_copyarea *are | |||
1312 | return; | 1337 | return; |
1313 | 1338 | ||
1314 | /* set the base addresses */ | 1339 | /* set the base addresses */ |
1315 | writel(par->screen.sm_addr, fbi->regs2d + SM501_2D_SOURCE_BASE); | 1340 | smc501_writel(par->screen.sm_addr, fbi->regs2d + SM501_2D_SOURCE_BASE); |
1316 | writel(par->screen.sm_addr, fbi->regs2d + SM501_2D_DESTINATION_BASE); | 1341 | smc501_writel(par->screen.sm_addr, |
1342 | fbi->regs2d + SM501_2D_DESTINATION_BASE); | ||
1317 | 1343 | ||
1318 | /* set the window width */ | 1344 | /* set the window width */ |
1319 | writel((info->var.xres << 16) | info->var.xres, | 1345 | smc501_writel((info->var.xres << 16) | info->var.xres, |
1320 | fbi->regs2d + SM501_2D_WINDOW_WIDTH); | 1346 | fbi->regs2d + SM501_2D_WINDOW_WIDTH); |
1321 | 1347 | ||
1322 | /* set window stride */ | 1348 | /* set window stride */ |
1323 | writel((info->var.xres_virtual << 16) | info->var.xres_virtual, | 1349 | smc501_writel((info->var.xres_virtual << 16) | info->var.xres_virtual, |
1324 | fbi->regs2d + SM501_2D_PITCH); | 1350 | fbi->regs2d + SM501_2D_PITCH); |
1325 | 1351 | ||
1326 | /* set data format */ | 1352 | /* set data format */ |
1327 | switch (info->var.bits_per_pixel) { | 1353 | switch (info->var.bits_per_pixel) { |
1328 | case 8: | 1354 | case 8: |
1329 | writel(0, fbi->regs2d + SM501_2D_STRETCH); | 1355 | smc501_writel(0, fbi->regs2d + SM501_2D_STRETCH); |
1330 | break; | 1356 | break; |
1331 | case 16: | 1357 | case 16: |
1332 | writel(0x00100000, fbi->regs2d + SM501_2D_STRETCH); | 1358 | smc501_writel(0x00100000, fbi->regs2d + SM501_2D_STRETCH); |
1333 | break; | 1359 | break; |
1334 | case 32: | 1360 | case 32: |
1335 | writel(0x00200000, fbi->regs2d + SM501_2D_STRETCH); | 1361 | smc501_writel(0x00200000, fbi->regs2d + SM501_2D_STRETCH); |
1336 | break; | 1362 | break; |
1337 | } | 1363 | } |
1338 | 1364 | ||
1339 | /* 2d compare mask */ | 1365 | /* 2d compare mask */ |
1340 | writel(0xffffffff, fbi->regs2d + SM501_2D_COLOR_COMPARE_MASK); | 1366 | smc501_writel(0xffffffff, fbi->regs2d + SM501_2D_COLOR_COMPARE_MASK); |
1341 | 1367 | ||
1342 | /* 2d mask */ | 1368 | /* 2d mask */ |
1343 | writel(0xffffffff, fbi->regs2d + SM501_2D_MASK); | 1369 | smc501_writel(0xffffffff, fbi->regs2d + SM501_2D_MASK); |
1344 | 1370 | ||
1345 | /* source and destination x y */ | 1371 | /* source and destination x y */ |
1346 | writel((sx << 16) | sy, fbi->regs2d + SM501_2D_SOURCE); | 1372 | smc501_writel((sx << 16) | sy, fbi->regs2d + SM501_2D_SOURCE); |
1347 | writel((dx << 16) | dy, fbi->regs2d + SM501_2D_DESTINATION); | 1373 | smc501_writel((dx << 16) | dy, fbi->regs2d + SM501_2D_DESTINATION); |
1348 | 1374 | ||
1349 | /* w/h */ | 1375 | /* w/h */ |
1350 | writel((width << 16) | height, fbi->regs2d + SM501_2D_DIMENSION); | 1376 | smc501_writel((width << 16) | height, fbi->regs2d + SM501_2D_DIMENSION); |
1351 | 1377 | ||
1352 | /* do area move */ | 1378 | /* do area move */ |
1353 | writel(0x800000cc | rtl, fbi->regs2d + SM501_2D_CONTROL); | 1379 | smc501_writel(0x800000cc | rtl, fbi->regs2d + SM501_2D_CONTROL); |
1354 | } | 1380 | } |
1355 | 1381 | ||
1356 | static void sm501fb_fillrect(struct fb_info *info, const struct fb_fillrect *rect) | 1382 | static void sm501fb_fillrect(struct fb_info *info, const struct fb_fillrect *rect) |
@@ -1372,47 +1398,49 @@ static void sm501fb_fillrect(struct fb_info *info, const struct fb_fillrect *rec | |||
1372 | return; | 1398 | return; |
1373 | 1399 | ||
1374 | /* set the base addresses */ | 1400 | /* set the base addresses */ |
1375 | writel(par->screen.sm_addr, fbi->regs2d + SM501_2D_SOURCE_BASE); | 1401 | smc501_writel(par->screen.sm_addr, fbi->regs2d + SM501_2D_SOURCE_BASE); |
1376 | writel(par->screen.sm_addr, fbi->regs2d + SM501_2D_DESTINATION_BASE); | 1402 | smc501_writel(par->screen.sm_addr, |
1403 | fbi->regs2d + SM501_2D_DESTINATION_BASE); | ||
1377 | 1404 | ||
1378 | /* set the window width */ | 1405 | /* set the window width */ |
1379 | writel((info->var.xres << 16) | info->var.xres, | 1406 | smc501_writel((info->var.xres << 16) | info->var.xres, |
1380 | fbi->regs2d + SM501_2D_WINDOW_WIDTH); | 1407 | fbi->regs2d + SM501_2D_WINDOW_WIDTH); |
1381 | 1408 | ||
1382 | /* set window stride */ | 1409 | /* set window stride */ |
1383 | writel((info->var.xres_virtual << 16) | info->var.xres_virtual, | 1410 | smc501_writel((info->var.xres_virtual << 16) | info->var.xres_virtual, |
1384 | fbi->regs2d + SM501_2D_PITCH); | 1411 | fbi->regs2d + SM501_2D_PITCH); |
1385 | 1412 | ||
1386 | /* set data format */ | 1413 | /* set data format */ |
1387 | switch (info->var.bits_per_pixel) { | 1414 | switch (info->var.bits_per_pixel) { |
1388 | case 8: | 1415 | case 8: |
1389 | writel(0, fbi->regs2d + SM501_2D_STRETCH); | 1416 | smc501_writel(0, fbi->regs2d + SM501_2D_STRETCH); |
1390 | break; | 1417 | break; |
1391 | case 16: | 1418 | case 16: |
1392 | writel(0x00100000, fbi->regs2d + SM501_2D_STRETCH); | 1419 | smc501_writel(0x00100000, fbi->regs2d + SM501_2D_STRETCH); |
1393 | break; | 1420 | break; |
1394 | case 32: | 1421 | case 32: |
1395 | writel(0x00200000, fbi->regs2d + SM501_2D_STRETCH); | 1422 | smc501_writel(0x00200000, fbi->regs2d + SM501_2D_STRETCH); |
1396 | break; | 1423 | break; |
1397 | } | 1424 | } |
1398 | 1425 | ||
1399 | /* 2d compare mask */ | 1426 | /* 2d compare mask */ |
1400 | writel(0xffffffff, fbi->regs2d + SM501_2D_COLOR_COMPARE_MASK); | 1427 | smc501_writel(0xffffffff, fbi->regs2d + SM501_2D_COLOR_COMPARE_MASK); |
1401 | 1428 | ||
1402 | /* 2d mask */ | 1429 | /* 2d mask */ |
1403 | writel(0xffffffff, fbi->regs2d + SM501_2D_MASK); | 1430 | smc501_writel(0xffffffff, fbi->regs2d + SM501_2D_MASK); |
1404 | 1431 | ||
1405 | /* colour */ | 1432 | /* colour */ |
1406 | writel(rect->color, fbi->regs2d + SM501_2D_FOREGROUND); | 1433 | smc501_writel(rect->color, fbi->regs2d + SM501_2D_FOREGROUND); |
1407 | 1434 | ||
1408 | /* x y */ | 1435 | /* x y */ |
1409 | writel((rect->dx << 16) | rect->dy, fbi->regs2d + SM501_2D_DESTINATION); | 1436 | smc501_writel((rect->dx << 16) | rect->dy, |
1437 | fbi->regs2d + SM501_2D_DESTINATION); | ||
1410 | 1438 | ||
1411 | /* w/h */ | 1439 | /* w/h */ |
1412 | writel((width << 16) | height, fbi->regs2d + SM501_2D_DIMENSION); | 1440 | smc501_writel((width << 16) | height, fbi->regs2d + SM501_2D_DIMENSION); |
1413 | 1441 | ||
1414 | /* do rectangle fill */ | 1442 | /* do rectangle fill */ |
1415 | writel(0x800100cc, fbi->regs2d + SM501_2D_CONTROL); | 1443 | smc501_writel(0x800100cc, fbi->regs2d + SM501_2D_CONTROL); |
1416 | } | 1444 | } |
1417 | 1445 | ||
1418 | 1446 | ||
@@ -1470,11 +1498,12 @@ static int sm501_init_cursor(struct fb_info *fbi, unsigned int reg_base) | |||
1470 | 1498 | ||
1471 | /* initialise the colour registers */ | 1499 | /* initialise the colour registers */ |
1472 | 1500 | ||
1473 | writel(par->cursor.sm_addr, par->cursor_regs + SM501_OFF_HWC_ADDR); | 1501 | smc501_writel(par->cursor.sm_addr, |
1502 | par->cursor_regs + SM501_OFF_HWC_ADDR); | ||
1474 | 1503 | ||
1475 | writel(0x00, par->cursor_regs + SM501_OFF_HWC_LOC); | 1504 | smc501_writel(0x00, par->cursor_regs + SM501_OFF_HWC_LOC); |
1476 | writel(0x00, par->cursor_regs + SM501_OFF_HWC_COLOR_1_2); | 1505 | smc501_writel(0x00, par->cursor_regs + SM501_OFF_HWC_COLOR_1_2); |
1477 | writel(0x00, par->cursor_regs + SM501_OFF_HWC_COLOR_3); | 1506 | smc501_writel(0x00, par->cursor_regs + SM501_OFF_HWC_COLOR_3); |
1478 | sm501fb_sync_regs(info); | 1507 | sm501fb_sync_regs(info); |
1479 | 1508 | ||
1480 | return 0; | 1509 | return 0; |
@@ -1581,7 +1610,7 @@ static int sm501fb_start(struct sm501fb_info *info, | |||
1581 | 1610 | ||
1582 | /* clear palette ram - undefined at power on */ | 1611 | /* clear palette ram - undefined at power on */ |
1583 | for (k = 0; k < (256 * 3); k++) | 1612 | for (k = 0; k < (256 * 3); k++) |
1584 | writel(0, info->regs + SM501_DC_PANEL_PALETTE + (k * 4)); | 1613 | smc501_writel(0, info->regs + SM501_DC_PANEL_PALETTE + (k * 4)); |
1585 | 1614 | ||
1586 | /* enable display controller */ | 1615 | /* enable display controller */ |
1587 | sm501_unit_power(dev->parent, SM501_GATE_DISPLAY, 1); | 1616 | sm501_unit_power(dev->parent, SM501_GATE_DISPLAY, 1); |
@@ -1649,20 +1678,20 @@ static int sm501fb_init_fb(struct fb_info *fb, | |||
1649 | switch (head) { | 1678 | switch (head) { |
1650 | case HEAD_CRT: | 1679 | case HEAD_CRT: |
1651 | pd = info->pdata->fb_crt; | 1680 | pd = info->pdata->fb_crt; |
1652 | ctrl = readl(info->regs + SM501_DC_CRT_CONTROL); | 1681 | ctrl = smc501_readl(info->regs + SM501_DC_CRT_CONTROL); |
1653 | enable = (ctrl & SM501_DC_CRT_CONTROL_ENABLE) ? 1 : 0; | 1682 | enable = (ctrl & SM501_DC_CRT_CONTROL_ENABLE) ? 1 : 0; |
1654 | 1683 | ||
1655 | /* ensure we set the correct source register */ | 1684 | /* ensure we set the correct source register */ |
1656 | if (info->pdata->fb_route != SM501_FB_CRT_PANEL) { | 1685 | if (info->pdata->fb_route != SM501_FB_CRT_PANEL) { |
1657 | ctrl |= SM501_DC_CRT_CONTROL_SEL; | 1686 | ctrl |= SM501_DC_CRT_CONTROL_SEL; |
1658 | writel(ctrl, info->regs + SM501_DC_CRT_CONTROL); | 1687 | smc501_writel(ctrl, info->regs + SM501_DC_CRT_CONTROL); |
1659 | } | 1688 | } |
1660 | 1689 | ||
1661 | break; | 1690 | break; |
1662 | 1691 | ||
1663 | case HEAD_PANEL: | 1692 | case HEAD_PANEL: |
1664 | pd = info->pdata->fb_pnl; | 1693 | pd = info->pdata->fb_pnl; |
1665 | ctrl = readl(info->regs + SM501_DC_PANEL_CONTROL); | 1694 | ctrl = smc501_readl(info->regs + SM501_DC_PANEL_CONTROL); |
1666 | enable = (ctrl & SM501_DC_PANEL_CONTROL_EN) ? 1 : 0; | 1695 | enable = (ctrl & SM501_DC_PANEL_CONTROL_EN) ? 1 : 0; |
1667 | break; | 1696 | break; |
1668 | 1697 | ||
@@ -1680,7 +1709,7 @@ static int sm501fb_init_fb(struct fb_info *fb, | |||
1680 | 1709 | ||
1681 | if (head == HEAD_CRT && info->pdata->fb_route == SM501_FB_CRT_PANEL) { | 1710 | if (head == HEAD_CRT && info->pdata->fb_route == SM501_FB_CRT_PANEL) { |
1682 | ctrl &= ~SM501_DC_CRT_CONTROL_SEL; | 1711 | ctrl &= ~SM501_DC_CRT_CONTROL_SEL; |
1683 | writel(ctrl, info->regs + SM501_DC_CRT_CONTROL); | 1712 | smc501_writel(ctrl, info->regs + SM501_DC_CRT_CONTROL); |
1684 | enable = 0; | 1713 | enable = 0; |
1685 | } | 1714 | } |
1686 | 1715 | ||
@@ -1700,6 +1729,15 @@ static int sm501fb_init_fb(struct fb_info *fb, | |||
1700 | FBINFO_HWACCEL_COPYAREA | FBINFO_HWACCEL_FILLRECT | | 1729 | FBINFO_HWACCEL_COPYAREA | FBINFO_HWACCEL_FILLRECT | |
1701 | FBINFO_HWACCEL_XPAN | FBINFO_HWACCEL_YPAN; | 1730 | FBINFO_HWACCEL_XPAN | FBINFO_HWACCEL_YPAN; |
1702 | 1731 | ||
1732 | #if defined(CONFIG_OF) | ||
1733 | #ifdef __BIG_ENDIAN | ||
1734 | if (of_get_property(info->dev->parent->of_node, "little-endian", NULL)) | ||
1735 | fb->flags |= FBINFO_FOREIGN_ENDIAN; | ||
1736 | #else | ||
1737 | if (of_get_property(info->dev->parent->of_node, "big-endian", NULL)) | ||
1738 | fb->flags |= FBINFO_FOREIGN_ENDIAN; | ||
1739 | #endif | ||
1740 | #endif | ||
1703 | /* fixed data */ | 1741 | /* fixed data */ |
1704 | 1742 | ||
1705 | fb->fix.type = FB_TYPE_PACKED_PIXELS; | 1743 | fb->fix.type = FB_TYPE_PACKED_PIXELS; |
@@ -1717,9 +1755,16 @@ static int sm501fb_init_fb(struct fb_info *fb, | |||
1717 | fb->var.vmode = FB_VMODE_NONINTERLACED; | 1755 | fb->var.vmode = FB_VMODE_NONINTERLACED; |
1718 | fb->var.bits_per_pixel = 16; | 1756 | fb->var.bits_per_pixel = 16; |
1719 | 1757 | ||
1758 | if (info->edid_data) { | ||
1759 | /* Now build modedb from EDID */ | ||
1760 | fb_edid_to_monspecs(info->edid_data, &fb->monspecs); | ||
1761 | fb_videomode_to_modelist(fb->monspecs.modedb, | ||
1762 | fb->monspecs.modedb_len, | ||
1763 | &fb->modelist); | ||
1764 | } | ||
1765 | |||
1720 | if (enable && (pd->flags & SM501FB_FLAG_USE_INIT_MODE) && 0) { | 1766 | if (enable && (pd->flags & SM501FB_FLAG_USE_INIT_MODE) && 0) { |
1721 | /* TODO read the mode from the current display */ | 1767 | /* TODO read the mode from the current display */ |
1722 | |||
1723 | } else { | 1768 | } else { |
1724 | if (pd->def_mode) { | 1769 | if (pd->def_mode) { |
1725 | dev_info(info->dev, "using supplied mode\n"); | 1770 | dev_info(info->dev, "using supplied mode\n"); |
@@ -1729,12 +1774,37 @@ static int sm501fb_init_fb(struct fb_info *fb, | |||
1729 | fb->var.xres_virtual = fb->var.xres; | 1774 | fb->var.xres_virtual = fb->var.xres; |
1730 | fb->var.yres_virtual = fb->var.yres; | 1775 | fb->var.yres_virtual = fb->var.yres; |
1731 | } else { | 1776 | } else { |
1732 | ret = fb_find_mode(&fb->var, fb, | 1777 | if (info->edid_data) { |
1778 | ret = fb_find_mode(&fb->var, fb, fb_mode, | ||
1779 | fb->monspecs.modedb, | ||
1780 | fb->monspecs.modedb_len, | ||
1781 | &sm501_default_mode, default_bpp); | ||
1782 | /* edid_data is no longer needed, free it */ | ||
1783 | kfree(info->edid_data); | ||
1784 | } else { | ||
1785 | ret = fb_find_mode(&fb->var, fb, | ||
1733 | NULL, NULL, 0, NULL, 8); | 1786 | NULL, NULL, 0, NULL, 8); |
1787 | } | ||
1734 | 1788 | ||
1735 | if (ret == 0 || ret == 4) { | 1789 | switch (ret) { |
1736 | dev_err(info->dev, | 1790 | case 1: |
1737 | "failed to get initial mode\n"); | 1791 | dev_info(info->dev, "using mode specified in " |
1792 | "@mode\n"); | ||
1793 | break; | ||
1794 | case 2: | ||
1795 | dev_info(info->dev, "using mode specified in " | ||
1796 | "@mode with ignored refresh rate\n"); | ||
1797 | break; | ||
1798 | case 3: | ||
1799 | dev_info(info->dev, "using mode default " | ||
1800 | "mode\n"); | ||
1801 | break; | ||
1802 | case 4: | ||
1803 | dev_info(info->dev, "using mode from list\n"); | ||
1804 | break; | ||
1805 | default: | ||
1806 | dev_info(info->dev, "ret = %d\n", ret); | ||
1807 | dev_info(info->dev, "failed to find mode\n"); | ||
1738 | return -EINVAL; | 1808 | return -EINVAL; |
1739 | } | 1809 | } |
1740 | } | 1810 | } |
@@ -1875,8 +1945,32 @@ static int __devinit sm501fb_probe(struct platform_device *pdev) | |||
1875 | } | 1945 | } |
1876 | 1946 | ||
1877 | if (info->pdata == NULL) { | 1947 | if (info->pdata == NULL) { |
1878 | dev_info(dev, "using default configuration data\n"); | 1948 | int found = 0; |
1949 | #if defined(CONFIG_OF) | ||
1950 | struct device_node *np = pdev->dev.parent->of_node; | ||
1951 | const u8 *prop; | ||
1952 | const char *cp; | ||
1953 | int len; | ||
1954 | |||
1879 | info->pdata = &sm501fb_def_pdata; | 1955 | info->pdata = &sm501fb_def_pdata; |
1956 | if (np) { | ||
1957 | /* Get EDID */ | ||
1958 | cp = of_get_property(np, "mode", &len); | ||
1959 | if (cp) | ||
1960 | strcpy(fb_mode, cp); | ||
1961 | prop = of_get_property(np, "edid", &len); | ||
1962 | if (prop && len == EDID_LENGTH) { | ||
1963 | info->edid_data = kmemdup(prop, EDID_LENGTH, | ||
1964 | GFP_KERNEL); | ||
1965 | if (info->edid_data) | ||
1966 | found = 1; | ||
1967 | } | ||
1968 | } | ||
1969 | #endif | ||
1970 | if (!found) { | ||
1971 | dev_info(dev, "using default configuration data\n"); | ||
1972 | info->pdata = &sm501fb_def_pdata; | ||
1973 | } | ||
1880 | } | 1974 | } |
1881 | 1975 | ||
1882 | /* probe for the presence of each panel */ | 1976 | /* probe for the presence of each panel */ |
@@ -2085,7 +2179,7 @@ static int sm501fb_suspend(struct platform_device *pdev, pm_message_t state) | |||
2085 | struct sm501fb_info *info = platform_get_drvdata(pdev); | 2179 | struct sm501fb_info *info = platform_get_drvdata(pdev); |
2086 | 2180 | ||
2087 | /* store crt control to resume with */ | 2181 | /* store crt control to resume with */ |
2088 | info->pm_crt_ctrl = readl(info->regs + SM501_DC_CRT_CONTROL); | 2182 | info->pm_crt_ctrl = smc501_readl(info->regs + SM501_DC_CRT_CONTROL); |
2089 | 2183 | ||
2090 | sm501fb_suspend_fb(info, HEAD_CRT); | 2184 | sm501fb_suspend_fb(info, HEAD_CRT); |
2091 | sm501fb_suspend_fb(info, HEAD_PANEL); | 2185 | sm501fb_suspend_fb(info, HEAD_PANEL); |
@@ -2109,10 +2203,10 @@ static int sm501fb_resume(struct platform_device *pdev) | |||
2109 | 2203 | ||
2110 | /* restore the items we want to be saved for crt control */ | 2204 | /* restore the items we want to be saved for crt control */ |
2111 | 2205 | ||
2112 | crt_ctrl = readl(info->regs + SM501_DC_CRT_CONTROL); | 2206 | crt_ctrl = smc501_readl(info->regs + SM501_DC_CRT_CONTROL); |
2113 | crt_ctrl &= ~SM501_CRT_CTRL_SAVE; | 2207 | crt_ctrl &= ~SM501_CRT_CTRL_SAVE; |
2114 | crt_ctrl |= info->pm_crt_ctrl & SM501_CRT_CTRL_SAVE; | 2208 | crt_ctrl |= info->pm_crt_ctrl & SM501_CRT_CTRL_SAVE; |
2115 | writel(crt_ctrl, info->regs + SM501_DC_CRT_CONTROL); | 2209 | smc501_writel(crt_ctrl, info->regs + SM501_DC_CRT_CONTROL); |
2116 | 2210 | ||
2117 | sm501fb_resume_fb(info, HEAD_CRT); | 2211 | sm501fb_resume_fb(info, HEAD_CRT); |
2118 | sm501fb_resume_fb(info, HEAD_PANEL); | 2212 | sm501fb_resume_fb(info, HEAD_PANEL); |
@@ -2149,6 +2243,11 @@ static void __exit sm501fb_cleanup(void) | |||
2149 | module_init(sm501fb_init); | 2243 | module_init(sm501fb_init); |
2150 | module_exit(sm501fb_cleanup); | 2244 | module_exit(sm501fb_cleanup); |
2151 | 2245 | ||
2246 | module_param_named(mode, fb_mode, charp, 0); | ||
2247 | MODULE_PARM_DESC(mode, | ||
2248 | "Specify resolution as \"<xres>x<yres>[-<bpp>][@<refresh>]\" "); | ||
2249 | module_param_named(bpp, default_bpp, ulong, 0); | ||
2250 | MODULE_PARM_DESC(bpp, "Specify bit-per-pixel if not specified mode"); | ||
2152 | MODULE_AUTHOR("Ben Dooks, Vincent Sanders"); | 2251 | MODULE_AUTHOR("Ben Dooks, Vincent Sanders"); |
2153 | MODULE_DESCRIPTION("SM501 Framebuffer driver"); | 2252 | MODULE_DESCRIPTION("SM501 Framebuffer driver"); |
2154 | MODULE_LICENSE("GPL v2"); | 2253 | MODULE_LICENSE("GPL v2"); |
diff --git a/drivers/video/svgalib.c b/drivers/video/svgalib.c index fdb45674e2f6..33df9ec91795 100644 --- a/drivers/video/svgalib.c +++ b/drivers/video/svgalib.c | |||
@@ -20,12 +20,12 @@ | |||
20 | 20 | ||
21 | 21 | ||
22 | /* Write a CRT register value spread across multiple registers */ | 22 | /* Write a CRT register value spread across multiple registers */ |
23 | void svga_wcrt_multi(const struct vga_regset *regset, u32 value) { | 23 | void svga_wcrt_multi(void __iomem *regbase, const struct vga_regset *regset, u32 value) |
24 | 24 | { | |
25 | u8 regval, bitval, bitnum; | 25 | u8 regval, bitval, bitnum; |
26 | 26 | ||
27 | while (regset->regnum != VGA_REGSET_END_VAL) { | 27 | while (regset->regnum != VGA_REGSET_END_VAL) { |
28 | regval = vga_rcrt(NULL, regset->regnum); | 28 | regval = vga_rcrt(regbase, regset->regnum); |
29 | bitnum = regset->lowbit; | 29 | bitnum = regset->lowbit; |
30 | while (bitnum <= regset->highbit) { | 30 | while (bitnum <= regset->highbit) { |
31 | bitval = 1 << bitnum; | 31 | bitval = 1 << bitnum; |
@@ -34,18 +34,18 @@ void svga_wcrt_multi(const struct vga_regset *regset, u32 value) { | |||
34 | bitnum ++; | 34 | bitnum ++; |
35 | value = value >> 1; | 35 | value = value >> 1; |
36 | } | 36 | } |
37 | vga_wcrt(NULL, regset->regnum, regval); | 37 | vga_wcrt(regbase, regset->regnum, regval); |
38 | regset ++; | 38 | regset ++; |
39 | } | 39 | } |
40 | } | 40 | } |
41 | 41 | ||
42 | /* Write a sequencer register value spread across multiple registers */ | 42 | /* Write a sequencer register value spread across multiple registers */ |
43 | void svga_wseq_multi(const struct vga_regset *regset, u32 value) { | 43 | void svga_wseq_multi(void __iomem *regbase, const struct vga_regset *regset, u32 value) |
44 | 44 | { | |
45 | u8 regval, bitval, bitnum; | 45 | u8 regval, bitval, bitnum; |
46 | 46 | ||
47 | while (regset->regnum != VGA_REGSET_END_VAL) { | 47 | while (regset->regnum != VGA_REGSET_END_VAL) { |
48 | regval = vga_rseq(NULL, regset->regnum); | 48 | regval = vga_rseq(regbase, regset->regnum); |
49 | bitnum = regset->lowbit; | 49 | bitnum = regset->lowbit; |
50 | while (bitnum <= regset->highbit) { | 50 | while (bitnum <= regset->highbit) { |
51 | bitval = 1 << bitnum; | 51 | bitval = 1 << bitnum; |
@@ -54,7 +54,7 @@ void svga_wseq_multi(const struct vga_regset *regset, u32 value) { | |||
54 | bitnum ++; | 54 | bitnum ++; |
55 | value = value >> 1; | 55 | value = value >> 1; |
56 | } | 56 | } |
57 | vga_wseq(NULL, regset->regnum, regval); | 57 | vga_wseq(regbase, regset->regnum, regval); |
58 | regset ++; | 58 | regset ++; |
59 | } | 59 | } |
60 | } | 60 | } |
@@ -75,95 +75,95 @@ static unsigned int svga_regset_size(const struct vga_regset *regset) | |||
75 | 75 | ||
76 | 76 | ||
77 | /* Set graphics controller registers to sane values */ | 77 | /* Set graphics controller registers to sane values */ |
78 | void svga_set_default_gfx_regs(void) | 78 | void svga_set_default_gfx_regs(void __iomem *regbase) |
79 | { | 79 | { |
80 | /* All standard GFX registers (GR00 - GR08) */ | 80 | /* All standard GFX registers (GR00 - GR08) */ |
81 | vga_wgfx(NULL, VGA_GFX_SR_VALUE, 0x00); | 81 | vga_wgfx(regbase, VGA_GFX_SR_VALUE, 0x00); |
82 | vga_wgfx(NULL, VGA_GFX_SR_ENABLE, 0x00); | 82 | vga_wgfx(regbase, VGA_GFX_SR_ENABLE, 0x00); |
83 | vga_wgfx(NULL, VGA_GFX_COMPARE_VALUE, 0x00); | 83 | vga_wgfx(regbase, VGA_GFX_COMPARE_VALUE, 0x00); |
84 | vga_wgfx(NULL, VGA_GFX_DATA_ROTATE, 0x00); | 84 | vga_wgfx(regbase, VGA_GFX_DATA_ROTATE, 0x00); |
85 | vga_wgfx(NULL, VGA_GFX_PLANE_READ, 0x00); | 85 | vga_wgfx(regbase, VGA_GFX_PLANE_READ, 0x00); |
86 | vga_wgfx(NULL, VGA_GFX_MODE, 0x00); | 86 | vga_wgfx(regbase, VGA_GFX_MODE, 0x00); |
87 | /* vga_wgfx(NULL, VGA_GFX_MODE, 0x20); */ | 87 | /* vga_wgfx(regbase, VGA_GFX_MODE, 0x20); */ |
88 | /* vga_wgfx(NULL, VGA_GFX_MODE, 0x40); */ | 88 | /* vga_wgfx(regbase, VGA_GFX_MODE, 0x40); */ |
89 | vga_wgfx(NULL, VGA_GFX_MISC, 0x05); | 89 | vga_wgfx(regbase, VGA_GFX_MISC, 0x05); |
90 | /* vga_wgfx(NULL, VGA_GFX_MISC, 0x01); */ | 90 | /* vga_wgfx(regbase, VGA_GFX_MISC, 0x01); */ |
91 | vga_wgfx(NULL, VGA_GFX_COMPARE_MASK, 0x0F); | 91 | vga_wgfx(regbase, VGA_GFX_COMPARE_MASK, 0x0F); |
92 | vga_wgfx(NULL, VGA_GFX_BIT_MASK, 0xFF); | 92 | vga_wgfx(regbase, VGA_GFX_BIT_MASK, 0xFF); |
93 | } | 93 | } |
94 | 94 | ||
95 | /* Set attribute controller registers to sane values */ | 95 | /* Set attribute controller registers to sane values */ |
96 | void svga_set_default_atc_regs(void) | 96 | void svga_set_default_atc_regs(void __iomem *regbase) |
97 | { | 97 | { |
98 | u8 count; | 98 | u8 count; |
99 | 99 | ||
100 | vga_r(NULL, 0x3DA); | 100 | vga_r(regbase, 0x3DA); |
101 | vga_w(NULL, VGA_ATT_W, 0x00); | 101 | vga_w(regbase, VGA_ATT_W, 0x00); |
102 | 102 | ||
103 | /* All standard ATC registers (AR00 - AR14) */ | 103 | /* All standard ATC registers (AR00 - AR14) */ |
104 | for (count = 0; count <= 0xF; count ++) | 104 | for (count = 0; count <= 0xF; count ++) |
105 | svga_wattr(count, count); | 105 | svga_wattr(regbase, count, count); |
106 | 106 | ||
107 | svga_wattr(VGA_ATC_MODE, 0x01); | 107 | svga_wattr(regbase, VGA_ATC_MODE, 0x01); |
108 | /* svga_wattr(VGA_ATC_MODE, 0x41); */ | 108 | /* svga_wattr(regbase, VGA_ATC_MODE, 0x41); */ |
109 | svga_wattr(VGA_ATC_OVERSCAN, 0x00); | 109 | svga_wattr(regbase, VGA_ATC_OVERSCAN, 0x00); |
110 | svga_wattr(VGA_ATC_PLANE_ENABLE, 0x0F); | 110 | svga_wattr(regbase, VGA_ATC_PLANE_ENABLE, 0x0F); |
111 | svga_wattr(VGA_ATC_PEL, 0x00); | 111 | svga_wattr(regbase, VGA_ATC_PEL, 0x00); |
112 | svga_wattr(VGA_ATC_COLOR_PAGE, 0x00); | 112 | svga_wattr(regbase, VGA_ATC_COLOR_PAGE, 0x00); |
113 | 113 | ||
114 | vga_r(NULL, 0x3DA); | 114 | vga_r(regbase, 0x3DA); |
115 | vga_w(NULL, VGA_ATT_W, 0x20); | 115 | vga_w(regbase, VGA_ATT_W, 0x20); |
116 | } | 116 | } |
117 | 117 | ||
118 | /* Set sequencer registers to sane values */ | 118 | /* Set sequencer registers to sane values */ |
119 | void svga_set_default_seq_regs(void) | 119 | void svga_set_default_seq_regs(void __iomem *regbase) |
120 | { | 120 | { |
121 | /* Standard sequencer registers (SR01 - SR04), SR00 is not set */ | 121 | /* Standard sequencer registers (SR01 - SR04), SR00 is not set */ |
122 | vga_wseq(NULL, VGA_SEQ_CLOCK_MODE, VGA_SR01_CHAR_CLK_8DOTS); | 122 | vga_wseq(regbase, VGA_SEQ_CLOCK_MODE, VGA_SR01_CHAR_CLK_8DOTS); |
123 | vga_wseq(NULL, VGA_SEQ_PLANE_WRITE, VGA_SR02_ALL_PLANES); | 123 | vga_wseq(regbase, VGA_SEQ_PLANE_WRITE, VGA_SR02_ALL_PLANES); |
124 | vga_wseq(NULL, VGA_SEQ_CHARACTER_MAP, 0x00); | 124 | vga_wseq(regbase, VGA_SEQ_CHARACTER_MAP, 0x00); |
125 | /* vga_wseq(NULL, VGA_SEQ_MEMORY_MODE, VGA_SR04_EXT_MEM | VGA_SR04_SEQ_MODE | VGA_SR04_CHN_4M); */ | 125 | /* vga_wseq(regbase, VGA_SEQ_MEMORY_MODE, VGA_SR04_EXT_MEM | VGA_SR04_SEQ_MODE | VGA_SR04_CHN_4M); */ |
126 | vga_wseq(NULL, VGA_SEQ_MEMORY_MODE, VGA_SR04_EXT_MEM | VGA_SR04_SEQ_MODE); | 126 | vga_wseq(regbase, VGA_SEQ_MEMORY_MODE, VGA_SR04_EXT_MEM | VGA_SR04_SEQ_MODE); |
127 | } | 127 | } |
128 | 128 | ||
129 | /* Set CRTC registers to sane values */ | 129 | /* Set CRTC registers to sane values */ |
130 | void svga_set_default_crt_regs(void) | 130 | void svga_set_default_crt_regs(void __iomem *regbase) |
131 | { | 131 | { |
132 | /* Standard CRT registers CR03 CR08 CR09 CR14 CR17 */ | 132 | /* Standard CRT registers CR03 CR08 CR09 CR14 CR17 */ |
133 | svga_wcrt_mask(0x03, 0x80, 0x80); /* Enable vertical retrace EVRA */ | 133 | svga_wcrt_mask(regbase, 0x03, 0x80, 0x80); /* Enable vertical retrace EVRA */ |
134 | vga_wcrt(NULL, VGA_CRTC_PRESET_ROW, 0); | 134 | vga_wcrt(regbase, VGA_CRTC_PRESET_ROW, 0); |
135 | svga_wcrt_mask(VGA_CRTC_MAX_SCAN, 0, 0x1F); | 135 | svga_wcrt_mask(regbase, VGA_CRTC_MAX_SCAN, 0, 0x1F); |
136 | vga_wcrt(NULL, VGA_CRTC_UNDERLINE, 0); | 136 | vga_wcrt(regbase, VGA_CRTC_UNDERLINE, 0); |
137 | vga_wcrt(NULL, VGA_CRTC_MODE, 0xE3); | 137 | vga_wcrt(regbase, VGA_CRTC_MODE, 0xE3); |
138 | } | 138 | } |
139 | 139 | ||
140 | void svga_set_textmode_vga_regs(void) | 140 | void svga_set_textmode_vga_regs(void __iomem *regbase) |
141 | { | 141 | { |
142 | /* svga_wseq_mask(0x1, 0x00, 0x01); */ /* Switch 8/9 pixel per char */ | 142 | /* svga_wseq_mask(regbase, 0x1, 0x00, 0x01); */ /* Switch 8/9 pixel per char */ |
143 | vga_wseq(NULL, VGA_SEQ_MEMORY_MODE, VGA_SR04_EXT_MEM); | 143 | vga_wseq(regbase, VGA_SEQ_MEMORY_MODE, VGA_SR04_EXT_MEM); |
144 | vga_wseq(NULL, VGA_SEQ_PLANE_WRITE, 0x03); | 144 | vga_wseq(regbase, VGA_SEQ_PLANE_WRITE, 0x03); |
145 | 145 | ||
146 | vga_wcrt(NULL, VGA_CRTC_MAX_SCAN, 0x0f); /* 0x4f */ | 146 | vga_wcrt(regbase, VGA_CRTC_MAX_SCAN, 0x0f); /* 0x4f */ |
147 | vga_wcrt(NULL, VGA_CRTC_UNDERLINE, 0x1f); | 147 | vga_wcrt(regbase, VGA_CRTC_UNDERLINE, 0x1f); |
148 | svga_wcrt_mask(VGA_CRTC_MODE, 0x23, 0x7f); | 148 | svga_wcrt_mask(regbase, VGA_CRTC_MODE, 0x23, 0x7f); |
149 | 149 | ||
150 | vga_wcrt(NULL, VGA_CRTC_CURSOR_START, 0x0d); | 150 | vga_wcrt(regbase, VGA_CRTC_CURSOR_START, 0x0d); |
151 | vga_wcrt(NULL, VGA_CRTC_CURSOR_END, 0x0e); | 151 | vga_wcrt(regbase, VGA_CRTC_CURSOR_END, 0x0e); |
152 | vga_wcrt(NULL, VGA_CRTC_CURSOR_HI, 0x00); | 152 | vga_wcrt(regbase, VGA_CRTC_CURSOR_HI, 0x00); |
153 | vga_wcrt(NULL, VGA_CRTC_CURSOR_LO, 0x00); | 153 | vga_wcrt(regbase, VGA_CRTC_CURSOR_LO, 0x00); |
154 | 154 | ||
155 | vga_wgfx(NULL, VGA_GFX_MODE, 0x10); /* Odd/even memory mode */ | 155 | vga_wgfx(regbase, VGA_GFX_MODE, 0x10); /* Odd/even memory mode */ |
156 | vga_wgfx(NULL, VGA_GFX_MISC, 0x0E); /* Misc graphics register - text mode enable */ | 156 | vga_wgfx(regbase, VGA_GFX_MISC, 0x0E); /* Misc graphics register - text mode enable */ |
157 | vga_wgfx(NULL, VGA_GFX_COMPARE_MASK, 0x00); | 157 | vga_wgfx(regbase, VGA_GFX_COMPARE_MASK, 0x00); |
158 | 158 | ||
159 | vga_r(NULL, 0x3DA); | 159 | vga_r(regbase, 0x3DA); |
160 | vga_w(NULL, VGA_ATT_W, 0x00); | 160 | vga_w(regbase, VGA_ATT_W, 0x00); |
161 | 161 | ||
162 | svga_wattr(0x10, 0x0C); /* Attribute Mode Control Register - text mode, blinking and line graphics */ | 162 | svga_wattr(regbase, 0x10, 0x0C); /* Attribute Mode Control Register - text mode, blinking and line graphics */ |
163 | svga_wattr(0x13, 0x08); /* Horizontal Pixel Panning Register */ | 163 | svga_wattr(regbase, 0x13, 0x08); /* Horizontal Pixel Panning Register */ |
164 | 164 | ||
165 | vga_r(NULL, 0x3DA); | 165 | vga_r(regbase, 0x3DA); |
166 | vga_w(NULL, VGA_ATT_W, 0x20); | 166 | vga_w(regbase, VGA_ATT_W, 0x20); |
167 | } | 167 | } |
168 | 168 | ||
169 | #if 0 | 169 | #if 0 |
@@ -299,7 +299,7 @@ void svga_tileblit(struct fb_info *info, struct fb_tileblit *blit) | |||
299 | } | 299 | } |
300 | 300 | ||
301 | /* Set cursor in text (tileblit) mode */ | 301 | /* Set cursor in text (tileblit) mode */ |
302 | void svga_tilecursor(struct fb_info *info, struct fb_tilecursor *cursor) | 302 | void svga_tilecursor(void __iomem *regbase, struct fb_info *info, struct fb_tilecursor *cursor) |
303 | { | 303 | { |
304 | u8 cs = 0x0d; | 304 | u8 cs = 0x0d; |
305 | u8 ce = 0x0e; | 305 | u8 ce = 0x0e; |
@@ -310,7 +310,7 @@ void svga_tilecursor(struct fb_info *info, struct fb_tilecursor *cursor) | |||
310 | if (! cursor -> mode) | 310 | if (! cursor -> mode) |
311 | return; | 311 | return; |
312 | 312 | ||
313 | svga_wcrt_mask(0x0A, 0x20, 0x20); /* disable cursor */ | 313 | svga_wcrt_mask(regbase, 0x0A, 0x20, 0x20); /* disable cursor */ |
314 | 314 | ||
315 | if (cursor -> shape == FB_TILE_CURSOR_NONE) | 315 | if (cursor -> shape == FB_TILE_CURSOR_NONE) |
316 | return; | 316 | return; |
@@ -334,11 +334,11 @@ void svga_tilecursor(struct fb_info *info, struct fb_tilecursor *cursor) | |||
334 | } | 334 | } |
335 | 335 | ||
336 | /* set cursor position */ | 336 | /* set cursor position */ |
337 | vga_wcrt(NULL, 0x0E, pos >> 8); | 337 | vga_wcrt(regbase, 0x0E, pos >> 8); |
338 | vga_wcrt(NULL, 0x0F, pos & 0xFF); | 338 | vga_wcrt(regbase, 0x0F, pos & 0xFF); |
339 | 339 | ||
340 | vga_wcrt(NULL, 0x0B, ce); /* set cursor end */ | 340 | vga_wcrt(regbase, 0x0B, ce); /* set cursor end */ |
341 | vga_wcrt(NULL, 0x0A, cs); /* set cursor start and enable it */ | 341 | vga_wcrt(regbase, 0x0A, cs); /* set cursor start and enable it */ |
342 | } | 342 | } |
343 | 343 | ||
344 | int svga_get_tilemax(struct fb_info *info) | 344 | int svga_get_tilemax(struct fb_info *info) |
@@ -507,8 +507,9 @@ int svga_check_timings(const struct svga_timing_regs *tm, struct fb_var_screenin | |||
507 | } | 507 | } |
508 | 508 | ||
509 | /* Set CRT timing registers */ | 509 | /* Set CRT timing registers */ |
510 | void svga_set_timings(const struct svga_timing_regs *tm, struct fb_var_screeninfo *var, | 510 | void svga_set_timings(void __iomem *regbase, const struct svga_timing_regs *tm, |
511 | u32 hmul, u32 hdiv, u32 vmul, u32 vdiv, u32 hborder, int node) | 511 | struct fb_var_screeninfo *var, |
512 | u32 hmul, u32 hdiv, u32 vmul, u32 vdiv, u32 hborder, int node) | ||
512 | { | 513 | { |
513 | u8 regval; | 514 | u8 regval; |
514 | u32 value; | 515 | u32 value; |
@@ -516,66 +517,66 @@ void svga_set_timings(const struct svga_timing_regs *tm, struct fb_var_screeninf | |||
516 | value = var->xres + var->left_margin + var->right_margin + var->hsync_len; | 517 | value = var->xres + var->left_margin + var->right_margin + var->hsync_len; |
517 | value = (value * hmul) / hdiv; | 518 | value = (value * hmul) / hdiv; |
518 | pr_debug("fb%d: horizontal total : %d\n", node, value); | 519 | pr_debug("fb%d: horizontal total : %d\n", node, value); |
519 | svga_wcrt_multi(tm->h_total_regs, (value / 8) - 5); | 520 | svga_wcrt_multi(regbase, tm->h_total_regs, (value / 8) - 5); |
520 | 521 | ||
521 | value = var->xres; | 522 | value = var->xres; |
522 | value = (value * hmul) / hdiv; | 523 | value = (value * hmul) / hdiv; |
523 | pr_debug("fb%d: horizontal display : %d\n", node, value); | 524 | pr_debug("fb%d: horizontal display : %d\n", node, value); |
524 | svga_wcrt_multi(tm->h_display_regs, (value / 8) - 1); | 525 | svga_wcrt_multi(regbase, tm->h_display_regs, (value / 8) - 1); |
525 | 526 | ||
526 | value = var->xres; | 527 | value = var->xres; |
527 | value = (value * hmul) / hdiv; | 528 | value = (value * hmul) / hdiv; |
528 | pr_debug("fb%d: horizontal blank start: %d\n", node, value); | 529 | pr_debug("fb%d: horizontal blank start: %d\n", node, value); |
529 | svga_wcrt_multi(tm->h_blank_start_regs, (value / 8) - 1 + hborder); | 530 | svga_wcrt_multi(regbase, tm->h_blank_start_regs, (value / 8) - 1 + hborder); |
530 | 531 | ||
531 | value = var->xres + var->left_margin + var->right_margin + var->hsync_len; | 532 | value = var->xres + var->left_margin + var->right_margin + var->hsync_len; |
532 | value = (value * hmul) / hdiv; | 533 | value = (value * hmul) / hdiv; |
533 | pr_debug("fb%d: horizontal blank end : %d\n", node, value); | 534 | pr_debug("fb%d: horizontal blank end : %d\n", node, value); |
534 | svga_wcrt_multi(tm->h_blank_end_regs, (value / 8) - 1 - hborder); | 535 | svga_wcrt_multi(regbase, tm->h_blank_end_regs, (value / 8) - 1 - hborder); |
535 | 536 | ||
536 | value = var->xres + var->right_margin; | 537 | value = var->xres + var->right_margin; |
537 | value = (value * hmul) / hdiv; | 538 | value = (value * hmul) / hdiv; |
538 | pr_debug("fb%d: horizontal sync start : %d\n", node, value); | 539 | pr_debug("fb%d: horizontal sync start : %d\n", node, value); |
539 | svga_wcrt_multi(tm->h_sync_start_regs, (value / 8)); | 540 | svga_wcrt_multi(regbase, tm->h_sync_start_regs, (value / 8)); |
540 | 541 | ||
541 | value = var->xres + var->right_margin + var->hsync_len; | 542 | value = var->xres + var->right_margin + var->hsync_len; |
542 | value = (value * hmul) / hdiv; | 543 | value = (value * hmul) / hdiv; |
543 | pr_debug("fb%d: horizontal sync end : %d\n", node, value); | 544 | pr_debug("fb%d: horizontal sync end : %d\n", node, value); |
544 | svga_wcrt_multi(tm->h_sync_end_regs, (value / 8)); | 545 | svga_wcrt_multi(regbase, tm->h_sync_end_regs, (value / 8)); |
545 | 546 | ||
546 | value = var->yres + var->upper_margin + var->lower_margin + var->vsync_len; | 547 | value = var->yres + var->upper_margin + var->lower_margin + var->vsync_len; |
547 | value = (value * vmul) / vdiv; | 548 | value = (value * vmul) / vdiv; |
548 | pr_debug("fb%d: vertical total : %d\n", node, value); | 549 | pr_debug("fb%d: vertical total : %d\n", node, value); |
549 | svga_wcrt_multi(tm->v_total_regs, value - 2); | 550 | svga_wcrt_multi(regbase, tm->v_total_regs, value - 2); |
550 | 551 | ||
551 | value = var->yres; | 552 | value = var->yres; |
552 | value = (value * vmul) / vdiv; | 553 | value = (value * vmul) / vdiv; |
553 | pr_debug("fb%d: vertical display : %d\n", node, value); | 554 | pr_debug("fb%d: vertical display : %d\n", node, value); |
554 | svga_wcrt_multi(tm->v_display_regs, value - 1); | 555 | svga_wcrt_multi(regbase, tm->v_display_regs, value - 1); |
555 | 556 | ||
556 | value = var->yres; | 557 | value = var->yres; |
557 | value = (value * vmul) / vdiv; | 558 | value = (value * vmul) / vdiv; |
558 | pr_debug("fb%d: vertical blank start : %d\n", node, value); | 559 | pr_debug("fb%d: vertical blank start : %d\n", node, value); |
559 | svga_wcrt_multi(tm->v_blank_start_regs, value); | 560 | svga_wcrt_multi(regbase, tm->v_blank_start_regs, value); |
560 | 561 | ||
561 | value = var->yres + var->upper_margin + var->lower_margin + var->vsync_len; | 562 | value = var->yres + var->upper_margin + var->lower_margin + var->vsync_len; |
562 | value = (value * vmul) / vdiv; | 563 | value = (value * vmul) / vdiv; |
563 | pr_debug("fb%d: vertical blank end : %d\n", node, value); | 564 | pr_debug("fb%d: vertical blank end : %d\n", node, value); |
564 | svga_wcrt_multi(tm->v_blank_end_regs, value - 2); | 565 | svga_wcrt_multi(regbase, tm->v_blank_end_regs, value - 2); |
565 | 566 | ||
566 | value = var->yres + var->lower_margin; | 567 | value = var->yres + var->lower_margin; |
567 | value = (value * vmul) / vdiv; | 568 | value = (value * vmul) / vdiv; |
568 | pr_debug("fb%d: vertical sync start : %d\n", node, value); | 569 | pr_debug("fb%d: vertical sync start : %d\n", node, value); |
569 | svga_wcrt_multi(tm->v_sync_start_regs, value); | 570 | svga_wcrt_multi(regbase, tm->v_sync_start_regs, value); |
570 | 571 | ||
571 | value = var->yres + var->lower_margin + var->vsync_len; | 572 | value = var->yres + var->lower_margin + var->vsync_len; |
572 | value = (value * vmul) / vdiv; | 573 | value = (value * vmul) / vdiv; |
573 | pr_debug("fb%d: vertical sync end : %d\n", node, value); | 574 | pr_debug("fb%d: vertical sync end : %d\n", node, value); |
574 | svga_wcrt_multi(tm->v_sync_end_regs, value); | 575 | svga_wcrt_multi(regbase, tm->v_sync_end_regs, value); |
575 | 576 | ||
576 | /* Set horizontal and vertical sync pulse polarity in misc register */ | 577 | /* Set horizontal and vertical sync pulse polarity in misc register */ |
577 | 578 | ||
578 | regval = vga_r(NULL, VGA_MIS_R); | 579 | regval = vga_r(regbase, VGA_MIS_R); |
579 | if (var->sync & FB_SYNC_HOR_HIGH_ACT) { | 580 | if (var->sync & FB_SYNC_HOR_HIGH_ACT) { |
580 | pr_debug("fb%d: positive horizontal sync\n", node); | 581 | pr_debug("fb%d: positive horizontal sync\n", node); |
581 | regval = regval & ~0x80; | 582 | regval = regval & ~0x80; |
@@ -590,7 +591,7 @@ void svga_set_timings(const struct svga_timing_regs *tm, struct fb_var_screeninf | |||
590 | pr_debug("fb%d: negative vertical sync\n\n", node); | 591 | pr_debug("fb%d: negative vertical sync\n\n", node); |
591 | regval = regval | 0x40; | 592 | regval = regval | 0x40; |
592 | } | 593 | } |
593 | vga_w(NULL, VGA_MIS_W, regval); | 594 | vga_w(regbase, VGA_MIS_W, regval); |
594 | } | 595 | } |
595 | 596 | ||
596 | 597 | ||
diff --git a/drivers/video/tcx.c b/drivers/video/tcx.c index 855b71993f61..07c66e946634 100644 --- a/drivers/video/tcx.c +++ b/drivers/video/tcx.c | |||
@@ -480,6 +480,7 @@ out_dealloc_cmap: | |||
480 | 480 | ||
481 | out_unmap_regs: | 481 | out_unmap_regs: |
482 | tcx_unmap_regs(op, info, par); | 482 | tcx_unmap_regs(op, info, par); |
483 | framebuffer_release(info); | ||
483 | 484 | ||
484 | out_err: | 485 | out_err: |
485 | return err; | 486 | return err; |
diff --git a/drivers/video/uvesafb.c b/drivers/video/uvesafb.c index 5180a215d781..7f8472cc993b 100644 --- a/drivers/video/uvesafb.c +++ b/drivers/video/uvesafb.c | |||
@@ -1552,8 +1552,7 @@ static void __devinit uvesafb_init_mtrr(struct fb_info *info) | |||
1552 | int rc; | 1552 | int rc; |
1553 | 1553 | ||
1554 | /* Find the largest power-of-two */ | 1554 | /* Find the largest power-of-two */ |
1555 | while (temp_size & (temp_size - 1)) | 1555 | temp_size = roundup_pow_of_two(temp_size); |
1556 | temp_size &= (temp_size - 1); | ||
1557 | 1556 | ||
1558 | /* Try and find a power of two to add */ | 1557 | /* Try and find a power of two to add */ |
1559 | do { | 1558 | do { |
@@ -1566,6 +1565,28 @@ static void __devinit uvesafb_init_mtrr(struct fb_info *info) | |||
1566 | #endif /* CONFIG_MTRR */ | 1565 | #endif /* CONFIG_MTRR */ |
1567 | } | 1566 | } |
1568 | 1567 | ||
1568 | static void __devinit uvesafb_ioremap(struct fb_info *info) | ||
1569 | { | ||
1570 | #ifdef CONFIG_X86 | ||
1571 | switch (mtrr) { | ||
1572 | case 1: /* uncachable */ | ||
1573 | info->screen_base = ioremap_nocache(info->fix.smem_start, info->fix.smem_len); | ||
1574 | break; | ||
1575 | case 2: /* write-back */ | ||
1576 | info->screen_base = ioremap_cache(info->fix.smem_start, info->fix.smem_len); | ||
1577 | break; | ||
1578 | case 3: /* write-combining */ | ||
1579 | info->screen_base = ioremap_wc(info->fix.smem_start, info->fix.smem_len); | ||
1580 | break; | ||
1581 | case 4: /* write-through */ | ||
1582 | default: | ||
1583 | info->screen_base = ioremap(info->fix.smem_start, info->fix.smem_len); | ||
1584 | break; | ||
1585 | } | ||
1586 | #else | ||
1587 | info->screen_base = ioremap(info->fix.smem_start, info->fix.smem_len); | ||
1588 | #endif /* CONFIG_X86 */ | ||
1589 | } | ||
1569 | 1590 | ||
1570 | static ssize_t uvesafb_show_vbe_ver(struct device *dev, | 1591 | static ssize_t uvesafb_show_vbe_ver(struct device *dev, |
1571 | struct device_attribute *attr, char *buf) | 1592 | struct device_attribute *attr, char *buf) |
@@ -1736,15 +1757,22 @@ static int __devinit uvesafb_probe(struct platform_device *dev) | |||
1736 | 1757 | ||
1737 | uvesafb_init_info(info, mode); | 1758 | uvesafb_init_info(info, mode); |
1738 | 1759 | ||
1760 | if (!request_region(0x3c0, 32, "uvesafb")) { | ||
1761 | printk(KERN_ERR "uvesafb: request region 0x3c0-0x3e0 failed\n"); | ||
1762 | err = -EIO; | ||
1763 | goto out_mode; | ||
1764 | } | ||
1765 | |||
1739 | if (!request_mem_region(info->fix.smem_start, info->fix.smem_len, | 1766 | if (!request_mem_region(info->fix.smem_start, info->fix.smem_len, |
1740 | "uvesafb")) { | 1767 | "uvesafb")) { |
1741 | printk(KERN_ERR "uvesafb: cannot reserve video memory at " | 1768 | printk(KERN_ERR "uvesafb: cannot reserve video memory at " |
1742 | "0x%lx\n", info->fix.smem_start); | 1769 | "0x%lx\n", info->fix.smem_start); |
1743 | err = -EIO; | 1770 | err = -EIO; |
1744 | goto out_mode; | 1771 | goto out_reg; |
1745 | } | 1772 | } |
1746 | 1773 | ||
1747 | info->screen_base = ioremap(info->fix.smem_start, info->fix.smem_len); | 1774 | uvesafb_init_mtrr(info); |
1775 | uvesafb_ioremap(info); | ||
1748 | 1776 | ||
1749 | if (!info->screen_base) { | 1777 | if (!info->screen_base) { |
1750 | printk(KERN_ERR | 1778 | printk(KERN_ERR |
@@ -1755,20 +1783,13 @@ static int __devinit uvesafb_probe(struct platform_device *dev) | |||
1755 | goto out_mem; | 1783 | goto out_mem; |
1756 | } | 1784 | } |
1757 | 1785 | ||
1758 | if (!request_region(0x3c0, 32, "uvesafb")) { | ||
1759 | printk(KERN_ERR "uvesafb: request region 0x3c0-0x3e0 failed\n"); | ||
1760 | err = -EIO; | ||
1761 | goto out_unmap; | ||
1762 | } | ||
1763 | |||
1764 | uvesafb_init_mtrr(info); | ||
1765 | platform_set_drvdata(dev, info); | 1786 | platform_set_drvdata(dev, info); |
1766 | 1787 | ||
1767 | if (register_framebuffer(info) < 0) { | 1788 | if (register_framebuffer(info) < 0) { |
1768 | printk(KERN_ERR | 1789 | printk(KERN_ERR |
1769 | "uvesafb: failed to register framebuffer device\n"); | 1790 | "uvesafb: failed to register framebuffer device\n"); |
1770 | err = -EINVAL; | 1791 | err = -EINVAL; |
1771 | goto out_reg; | 1792 | goto out_unmap; |
1772 | } | 1793 | } |
1773 | 1794 | ||
1774 | printk(KERN_INFO "uvesafb: framebuffer at 0x%lx, mapped to 0x%p, " | 1795 | printk(KERN_INFO "uvesafb: framebuffer at 0x%lx, mapped to 0x%p, " |
@@ -1785,12 +1806,12 @@ static int __devinit uvesafb_probe(struct platform_device *dev) | |||
1785 | 1806 | ||
1786 | return 0; | 1807 | return 0; |
1787 | 1808 | ||
1788 | out_reg: | ||
1789 | release_region(0x3c0, 32); | ||
1790 | out_unmap: | 1809 | out_unmap: |
1791 | iounmap(info->screen_base); | 1810 | iounmap(info->screen_base); |
1792 | out_mem: | 1811 | out_mem: |
1793 | release_mem_region(info->fix.smem_start, info->fix.smem_len); | 1812 | release_mem_region(info->fix.smem_start, info->fix.smem_len); |
1813 | out_reg: | ||
1814 | release_region(0x3c0, 32); | ||
1794 | out_mode: | 1815 | out_mode: |
1795 | if (!list_empty(&info->modelist)) | 1816 | if (!list_empty(&info->modelist)) |
1796 | fb_destroy_modelist(&info->modelist); | 1817 | fb_destroy_modelist(&info->modelist); |
diff --git a/drivers/video/vermilion/vermilion.c b/drivers/video/vermilion/vermilion.c index 931a567f9aff..970e43d13f52 100644 --- a/drivers/video/vermilion/vermilion.c +++ b/drivers/video/vermilion/vermilion.c | |||
@@ -891,8 +891,7 @@ static int vmlfb_set_par(struct fb_info *info) | |||
891 | int ret; | 891 | int ret; |
892 | 892 | ||
893 | mutex_lock(&vml_mutex); | 893 | mutex_lock(&vml_mutex); |
894 | list_del(&vinfo->head); | 894 | list_move(&vinfo->head, (subsys) ? &global_has_mode : &global_no_mode); |
895 | list_add(&vinfo->head, (subsys) ? &global_has_mode : &global_no_mode); | ||
896 | ret = vmlfb_set_par_locked(vinfo); | 895 | ret = vmlfb_set_par_locked(vinfo); |
897 | 896 | ||
898 | mutex_unlock(&vml_mutex); | 897 | mutex_unlock(&vml_mutex); |
diff --git a/drivers/video/vesafb.c b/drivers/video/vesafb.c index 6a069d047914..a99bbe86db13 100644 --- a/drivers/video/vesafb.c +++ b/drivers/video/vesafb.c | |||
@@ -303,19 +303,6 @@ static int __init vesafb_probe(struct platform_device *dev) | |||
303 | info->apertures->ranges[0].base = screen_info.lfb_base; | 303 | info->apertures->ranges[0].base = screen_info.lfb_base; |
304 | info->apertures->ranges[0].size = size_total; | 304 | info->apertures->ranges[0].size = size_total; |
305 | 305 | ||
306 | info->screen_base = ioremap(vesafb_fix.smem_start, vesafb_fix.smem_len); | ||
307 | if (!info->screen_base) { | ||
308 | printk(KERN_ERR | ||
309 | "vesafb: abort, cannot ioremap video memory 0x%x @ 0x%lx\n", | ||
310 | vesafb_fix.smem_len, vesafb_fix.smem_start); | ||
311 | err = -EIO; | ||
312 | goto err; | ||
313 | } | ||
314 | |||
315 | printk(KERN_INFO "vesafb: framebuffer at 0x%lx, mapped to 0x%p, " | ||
316 | "using %dk, total %dk\n", | ||
317 | vesafb_fix.smem_start, info->screen_base, | ||
318 | size_remap/1024, size_total/1024); | ||
319 | printk(KERN_INFO "vesafb: mode is %dx%dx%d, linelength=%d, pages=%d\n", | 306 | printk(KERN_INFO "vesafb: mode is %dx%dx%d, linelength=%d, pages=%d\n", |
320 | vesafb_defined.xres, vesafb_defined.yres, vesafb_defined.bits_per_pixel, vesafb_fix.line_length, screen_info.pages); | 307 | vesafb_defined.xres, vesafb_defined.yres, vesafb_defined.bits_per_pixel, vesafb_fix.line_length, screen_info.pages); |
321 | 308 | ||
@@ -438,8 +425,7 @@ static int __init vesafb_probe(struct platform_device *dev) | |||
438 | int rc; | 425 | int rc; |
439 | 426 | ||
440 | /* Find the largest power-of-two */ | 427 | /* Find the largest power-of-two */ |
441 | while (temp_size & (temp_size - 1)) | 428 | temp_size = roundup_pow_of_two(temp_size); |
442 | temp_size &= (temp_size - 1); | ||
443 | 429 | ||
444 | /* Try and find a power of two to add */ | 430 | /* Try and find a power of two to add */ |
445 | do { | 431 | do { |
@@ -451,6 +437,34 @@ static int __init vesafb_probe(struct platform_device *dev) | |||
451 | } | 437 | } |
452 | #endif | 438 | #endif |
453 | 439 | ||
440 | switch (mtrr) { | ||
441 | case 1: /* uncachable */ | ||
442 | info->screen_base = ioremap_nocache(vesafb_fix.smem_start, vesafb_fix.smem_len); | ||
443 | break; | ||
444 | case 2: /* write-back */ | ||
445 | info->screen_base = ioremap_cache(vesafb_fix.smem_start, vesafb_fix.smem_len); | ||
446 | break; | ||
447 | case 3: /* write-combining */ | ||
448 | info->screen_base = ioremap_wc(vesafb_fix.smem_start, vesafb_fix.smem_len); | ||
449 | break; | ||
450 | case 4: /* write-through */ | ||
451 | default: | ||
452 | info->screen_base = ioremap(vesafb_fix.smem_start, vesafb_fix.smem_len); | ||
453 | break; | ||
454 | } | ||
455 | if (!info->screen_base) { | ||
456 | printk(KERN_ERR | ||
457 | "vesafb: abort, cannot ioremap video memory 0x%x @ 0x%lx\n", | ||
458 | vesafb_fix.smem_len, vesafb_fix.smem_start); | ||
459 | err = -EIO; | ||
460 | goto err; | ||
461 | } | ||
462 | |||
463 | printk(KERN_INFO "vesafb: framebuffer at 0x%lx, mapped to 0x%p, " | ||
464 | "using %dk, total %dk\n", | ||
465 | vesafb_fix.smem_start, info->screen_base, | ||
466 | size_remap/1024, size_total/1024); | ||
467 | |||
454 | info->fbops = &vesafb_ops; | 468 | info->fbops = &vesafb_ops; |
455 | info->var = vesafb_defined; | 469 | info->var = vesafb_defined; |
456 | info->fix = vesafb_fix; | 470 | info->fix = vesafb_fix; |
diff --git a/drivers/video/vt8623fb.c b/drivers/video/vt8623fb.c index a2965ab92cfb..f9b3e3dc2421 100644 --- a/drivers/video/vt8623fb.c +++ b/drivers/video/vt8623fb.c | |||
@@ -121,13 +121,19 @@ MODULE_PARM_DESC(mtrr, "Enable write-combining with MTRR (1=enable, 0=disable, d | |||
121 | 121 | ||
122 | /* ------------------------------------------------------------------------- */ | 122 | /* ------------------------------------------------------------------------- */ |
123 | 123 | ||
124 | static void vt8623fb_tilecursor(struct fb_info *info, struct fb_tilecursor *cursor) | ||
125 | { | ||
126 | struct vt8623fb_info *par = info->par; | ||
127 | |||
128 | svga_tilecursor(par->state.vgabase, info, cursor); | ||
129 | } | ||
124 | 130 | ||
125 | static struct fb_tile_ops vt8623fb_tile_ops = { | 131 | static struct fb_tile_ops vt8623fb_tile_ops = { |
126 | .fb_settile = svga_settile, | 132 | .fb_settile = svga_settile, |
127 | .fb_tilecopy = svga_tilecopy, | 133 | .fb_tilecopy = svga_tilecopy, |
128 | .fb_tilefill = svga_tilefill, | 134 | .fb_tilefill = svga_tilefill, |
129 | .fb_tileblit = svga_tileblit, | 135 | .fb_tileblit = svga_tileblit, |
130 | .fb_tilecursor = svga_tilecursor, | 136 | .fb_tilecursor = vt8623fb_tilecursor, |
131 | .fb_get_tilemax = svga_get_tilemax, | 137 | .fb_get_tilemax = svga_get_tilemax, |
132 | }; | 138 | }; |
133 | 139 | ||
@@ -253,6 +259,7 @@ static void vt8623fb_fillrect(struct fb_info *info, const struct fb_fillrect *re | |||
253 | 259 | ||
254 | static void vt8623_set_pixclock(struct fb_info *info, u32 pixclock) | 260 | static void vt8623_set_pixclock(struct fb_info *info, u32 pixclock) |
255 | { | 261 | { |
262 | struct vt8623fb_info *par = info->par; | ||
256 | u16 m, n, r; | 263 | u16 m, n, r; |
257 | u8 regval; | 264 | u8 regval; |
258 | int rv; | 265 | int rv; |
@@ -264,18 +271,18 @@ static void vt8623_set_pixclock(struct fb_info *info, u32 pixclock) | |||
264 | } | 271 | } |
265 | 272 | ||
266 | /* Set VGA misc register */ | 273 | /* Set VGA misc register */ |
267 | regval = vga_r(NULL, VGA_MIS_R); | 274 | regval = vga_r(par->state.vgabase, VGA_MIS_R); |
268 | vga_w(NULL, VGA_MIS_W, regval | VGA_MIS_ENB_PLL_LOAD); | 275 | vga_w(par->state.vgabase, VGA_MIS_W, regval | VGA_MIS_ENB_PLL_LOAD); |
269 | 276 | ||
270 | /* Set clock registers */ | 277 | /* Set clock registers */ |
271 | vga_wseq(NULL, 0x46, (n | (r << 6))); | 278 | vga_wseq(par->state.vgabase, 0x46, (n | (r << 6))); |
272 | vga_wseq(NULL, 0x47, m); | 279 | vga_wseq(par->state.vgabase, 0x47, m); |
273 | 280 | ||
274 | udelay(1000); | 281 | udelay(1000); |
275 | 282 | ||
276 | /* PLL reset */ | 283 | /* PLL reset */ |
277 | svga_wseq_mask(0x40, 0x02, 0x02); | 284 | svga_wseq_mask(par->state.vgabase, 0x40, 0x02, 0x02); |
278 | svga_wseq_mask(0x40, 0x00, 0x02); | 285 | svga_wseq_mask(par->state.vgabase, 0x40, 0x00, 0x02); |
279 | } | 286 | } |
280 | 287 | ||
281 | 288 | ||
@@ -285,7 +292,10 @@ static int vt8623fb_open(struct fb_info *info, int user) | |||
285 | 292 | ||
286 | mutex_lock(&(par->open_lock)); | 293 | mutex_lock(&(par->open_lock)); |
287 | if (par->ref_count == 0) { | 294 | if (par->ref_count == 0) { |
295 | void __iomem *vgabase = par->state.vgabase; | ||
296 | |||
288 | memset(&(par->state), 0, sizeof(struct vgastate)); | 297 | memset(&(par->state), 0, sizeof(struct vgastate)); |
298 | par->state.vgabase = vgabase; | ||
289 | par->state.flags = VGA_SAVE_MODE | VGA_SAVE_FONTS | VGA_SAVE_CMAP; | 299 | par->state.flags = VGA_SAVE_MODE | VGA_SAVE_FONTS | VGA_SAVE_CMAP; |
290 | par->state.num_crtc = 0xA2; | 300 | par->state.num_crtc = 0xA2; |
291 | par->state.num_seq = 0x50; | 301 | par->state.num_seq = 0x50; |
@@ -373,6 +383,7 @@ static int vt8623fb_check_var(struct fb_var_screeninfo *var, struct fb_info *inf | |||
373 | static int vt8623fb_set_par(struct fb_info *info) | 383 | static int vt8623fb_set_par(struct fb_info *info) |
374 | { | 384 | { |
375 | u32 mode, offset_value, fetch_value, screen_size; | 385 | u32 mode, offset_value, fetch_value, screen_size; |
386 | struct vt8623fb_info *par = info->par; | ||
376 | u32 bpp = info->var.bits_per_pixel; | 387 | u32 bpp = info->var.bits_per_pixel; |
377 | 388 | ||
378 | if (bpp != 0) { | 389 | if (bpp != 0) { |
@@ -414,82 +425,82 @@ static int vt8623fb_set_par(struct fb_info *info) | |||
414 | info->var.activate = FB_ACTIVATE_NOW; | 425 | info->var.activate = FB_ACTIVATE_NOW; |
415 | 426 | ||
416 | /* Unlock registers */ | 427 | /* Unlock registers */ |
417 | svga_wseq_mask(0x10, 0x01, 0x01); | 428 | svga_wseq_mask(par->state.vgabase, 0x10, 0x01, 0x01); |
418 | svga_wcrt_mask(0x11, 0x00, 0x80); | 429 | svga_wcrt_mask(par->state.vgabase, 0x11, 0x00, 0x80); |
419 | svga_wcrt_mask(0x47, 0x00, 0x01); | 430 | svga_wcrt_mask(par->state.vgabase, 0x47, 0x00, 0x01); |
420 | 431 | ||
421 | /* Device, screen and sync off */ | 432 | /* Device, screen and sync off */ |
422 | svga_wseq_mask(0x01, 0x20, 0x20); | 433 | svga_wseq_mask(par->state.vgabase, 0x01, 0x20, 0x20); |
423 | svga_wcrt_mask(0x36, 0x30, 0x30); | 434 | svga_wcrt_mask(par->state.vgabase, 0x36, 0x30, 0x30); |
424 | svga_wcrt_mask(0x17, 0x00, 0x80); | 435 | svga_wcrt_mask(par->state.vgabase, 0x17, 0x00, 0x80); |
425 | 436 | ||
426 | /* Set default values */ | 437 | /* Set default values */ |
427 | svga_set_default_gfx_regs(); | 438 | svga_set_default_gfx_regs(par->state.vgabase); |
428 | svga_set_default_atc_regs(); | 439 | svga_set_default_atc_regs(par->state.vgabase); |
429 | svga_set_default_seq_regs(); | 440 | svga_set_default_seq_regs(par->state.vgabase); |
430 | svga_set_default_crt_regs(); | 441 | svga_set_default_crt_regs(par->state.vgabase); |
431 | svga_wcrt_multi(vt8623_line_compare_regs, 0xFFFFFFFF); | 442 | svga_wcrt_multi(par->state.vgabase, vt8623_line_compare_regs, 0xFFFFFFFF); |
432 | svga_wcrt_multi(vt8623_start_address_regs, 0); | 443 | svga_wcrt_multi(par->state.vgabase, vt8623_start_address_regs, 0); |
433 | 444 | ||
434 | svga_wcrt_multi(vt8623_offset_regs, offset_value); | 445 | svga_wcrt_multi(par->state.vgabase, vt8623_offset_regs, offset_value); |
435 | svga_wseq_multi(vt8623_fetch_count_regs, fetch_value); | 446 | svga_wseq_multi(par->state.vgabase, vt8623_fetch_count_regs, fetch_value); |
436 | 447 | ||
437 | /* Clear H/V Skew */ | 448 | /* Clear H/V Skew */ |
438 | svga_wcrt_mask(0x03, 0x00, 0x60); | 449 | svga_wcrt_mask(par->state.vgabase, 0x03, 0x00, 0x60); |
439 | svga_wcrt_mask(0x05, 0x00, 0x60); | 450 | svga_wcrt_mask(par->state.vgabase, 0x05, 0x00, 0x60); |
440 | 451 | ||
441 | if (info->var.vmode & FB_VMODE_DOUBLE) | 452 | if (info->var.vmode & FB_VMODE_DOUBLE) |
442 | svga_wcrt_mask(0x09, 0x80, 0x80); | 453 | svga_wcrt_mask(par->state.vgabase, 0x09, 0x80, 0x80); |
443 | else | 454 | else |
444 | svga_wcrt_mask(0x09, 0x00, 0x80); | 455 | svga_wcrt_mask(par->state.vgabase, 0x09, 0x00, 0x80); |
445 | 456 | ||
446 | svga_wseq_mask(0x1E, 0xF0, 0xF0); // DI/DVP bus | 457 | svga_wseq_mask(par->state.vgabase, 0x1E, 0xF0, 0xF0); // DI/DVP bus |
447 | svga_wseq_mask(0x2A, 0x0F, 0x0F); // DI/DVP bus | 458 | svga_wseq_mask(par->state.vgabase, 0x2A, 0x0F, 0x0F); // DI/DVP bus |
448 | svga_wseq_mask(0x16, 0x08, 0xBF); // FIFO read threshold | 459 | svga_wseq_mask(par->state.vgabase, 0x16, 0x08, 0xBF); // FIFO read threshold |
449 | vga_wseq(NULL, 0x17, 0x1F); // FIFO depth | 460 | vga_wseq(par->state.vgabase, 0x17, 0x1F); // FIFO depth |
450 | vga_wseq(NULL, 0x18, 0x4E); | 461 | vga_wseq(par->state.vgabase, 0x18, 0x4E); |
451 | svga_wseq_mask(0x1A, 0x08, 0x08); // enable MMIO ? | 462 | svga_wseq_mask(par->state.vgabase, 0x1A, 0x08, 0x08); // enable MMIO ? |
452 | 463 | ||
453 | vga_wcrt(NULL, 0x32, 0x00); | 464 | vga_wcrt(par->state.vgabase, 0x32, 0x00); |
454 | vga_wcrt(NULL, 0x34, 0x00); | 465 | vga_wcrt(par->state.vgabase, 0x34, 0x00); |
455 | vga_wcrt(NULL, 0x6A, 0x80); | 466 | vga_wcrt(par->state.vgabase, 0x6A, 0x80); |
456 | vga_wcrt(NULL, 0x6A, 0xC0); | 467 | vga_wcrt(par->state.vgabase, 0x6A, 0xC0); |
457 | 468 | ||
458 | vga_wgfx(NULL, 0x20, 0x00); | 469 | vga_wgfx(par->state.vgabase, 0x20, 0x00); |
459 | vga_wgfx(NULL, 0x21, 0x00); | 470 | vga_wgfx(par->state.vgabase, 0x21, 0x00); |
460 | vga_wgfx(NULL, 0x22, 0x00); | 471 | vga_wgfx(par->state.vgabase, 0x22, 0x00); |
461 | 472 | ||
462 | /* Set SR15 according to number of bits per pixel */ | 473 | /* Set SR15 according to number of bits per pixel */ |
463 | mode = svga_match_format(vt8623fb_formats, &(info->var), &(info->fix)); | 474 | mode = svga_match_format(vt8623fb_formats, &(info->var), &(info->fix)); |
464 | switch (mode) { | 475 | switch (mode) { |
465 | case 0: | 476 | case 0: |
466 | pr_debug("fb%d: text mode\n", info->node); | 477 | pr_debug("fb%d: text mode\n", info->node); |
467 | svga_set_textmode_vga_regs(); | 478 | svga_set_textmode_vga_regs(par->state.vgabase); |
468 | svga_wseq_mask(0x15, 0x00, 0xFE); | 479 | svga_wseq_mask(par->state.vgabase, 0x15, 0x00, 0xFE); |
469 | svga_wcrt_mask(0x11, 0x60, 0x70); | 480 | svga_wcrt_mask(par->state.vgabase, 0x11, 0x60, 0x70); |
470 | break; | 481 | break; |
471 | case 1: | 482 | case 1: |
472 | pr_debug("fb%d: 4 bit pseudocolor\n", info->node); | 483 | pr_debug("fb%d: 4 bit pseudocolor\n", info->node); |
473 | vga_wgfx(NULL, VGA_GFX_MODE, 0x40); | 484 | vga_wgfx(par->state.vgabase, VGA_GFX_MODE, 0x40); |
474 | svga_wseq_mask(0x15, 0x20, 0xFE); | 485 | svga_wseq_mask(par->state.vgabase, 0x15, 0x20, 0xFE); |
475 | svga_wcrt_mask(0x11, 0x00, 0x70); | 486 | svga_wcrt_mask(par->state.vgabase, 0x11, 0x00, 0x70); |
476 | break; | 487 | break; |
477 | case 2: | 488 | case 2: |
478 | pr_debug("fb%d: 4 bit pseudocolor, planar\n", info->node); | 489 | pr_debug("fb%d: 4 bit pseudocolor, planar\n", info->node); |
479 | svga_wseq_mask(0x15, 0x00, 0xFE); | 490 | svga_wseq_mask(par->state.vgabase, 0x15, 0x00, 0xFE); |
480 | svga_wcrt_mask(0x11, 0x00, 0x70); | 491 | svga_wcrt_mask(par->state.vgabase, 0x11, 0x00, 0x70); |
481 | break; | 492 | break; |
482 | case 3: | 493 | case 3: |
483 | pr_debug("fb%d: 8 bit pseudocolor\n", info->node); | 494 | pr_debug("fb%d: 8 bit pseudocolor\n", info->node); |
484 | svga_wseq_mask(0x15, 0x22, 0xFE); | 495 | svga_wseq_mask(par->state.vgabase, 0x15, 0x22, 0xFE); |
485 | break; | 496 | break; |
486 | case 4: | 497 | case 4: |
487 | pr_debug("fb%d: 5/6/5 truecolor\n", info->node); | 498 | pr_debug("fb%d: 5/6/5 truecolor\n", info->node); |
488 | svga_wseq_mask(0x15, 0xB6, 0xFE); | 499 | svga_wseq_mask(par->state.vgabase, 0x15, 0xB6, 0xFE); |
489 | break; | 500 | break; |
490 | case 5: | 501 | case 5: |
491 | pr_debug("fb%d: 8/8/8 truecolor\n", info->node); | 502 | pr_debug("fb%d: 8/8/8 truecolor\n", info->node); |
492 | svga_wseq_mask(0x15, 0xAE, 0xFE); | 503 | svga_wseq_mask(par->state.vgabase, 0x15, 0xAE, 0xFE); |
493 | break; | 504 | break; |
494 | default: | 505 | default: |
495 | printk(KERN_ERR "vt8623fb: unsupported mode - bug\n"); | 506 | printk(KERN_ERR "vt8623fb: unsupported mode - bug\n"); |
@@ -497,16 +508,16 @@ static int vt8623fb_set_par(struct fb_info *info) | |||
497 | } | 508 | } |
498 | 509 | ||
499 | vt8623_set_pixclock(info, info->var.pixclock); | 510 | vt8623_set_pixclock(info, info->var.pixclock); |
500 | svga_set_timings(&vt8623_timing_regs, &(info->var), 1, 1, | 511 | svga_set_timings(par->state.vgabase, &vt8623_timing_regs, &(info->var), 1, 1, |
501 | (info->var.vmode & FB_VMODE_DOUBLE) ? 2 : 1, 1, | 512 | (info->var.vmode & FB_VMODE_DOUBLE) ? 2 : 1, 1, |
502 | 1, info->node); | 513 | 1, info->node); |
503 | 514 | ||
504 | memset_io(info->screen_base, 0x00, screen_size); | 515 | memset_io(info->screen_base, 0x00, screen_size); |
505 | 516 | ||
506 | /* Device and screen back on */ | 517 | /* Device and screen back on */ |
507 | svga_wcrt_mask(0x17, 0x80, 0x80); | 518 | svga_wcrt_mask(par->state.vgabase, 0x17, 0x80, 0x80); |
508 | svga_wcrt_mask(0x36, 0x00, 0x30); | 519 | svga_wcrt_mask(par->state.vgabase, 0x36, 0x00, 0x30); |
509 | svga_wseq_mask(0x01, 0x00, 0x20); | 520 | svga_wseq_mask(par->state.vgabase, 0x01, 0x00, 0x20); |
510 | 521 | ||
511 | return 0; | 522 | return 0; |
512 | } | 523 | } |
@@ -569,31 +580,33 @@ static int vt8623fb_setcolreg(u_int regno, u_int red, u_int green, u_int blue, | |||
569 | 580 | ||
570 | static int vt8623fb_blank(int blank_mode, struct fb_info *info) | 581 | static int vt8623fb_blank(int blank_mode, struct fb_info *info) |
571 | { | 582 | { |
583 | struct vt8623fb_info *par = info->par; | ||
584 | |||
572 | switch (blank_mode) { | 585 | switch (blank_mode) { |
573 | case FB_BLANK_UNBLANK: | 586 | case FB_BLANK_UNBLANK: |
574 | pr_debug("fb%d: unblank\n", info->node); | 587 | pr_debug("fb%d: unblank\n", info->node); |
575 | svga_wcrt_mask(0x36, 0x00, 0x30); | 588 | svga_wcrt_mask(par->state.vgabase, 0x36, 0x00, 0x30); |
576 | svga_wseq_mask(0x01, 0x00, 0x20); | 589 | svga_wseq_mask(par->state.vgabase, 0x01, 0x00, 0x20); |
577 | break; | 590 | break; |
578 | case FB_BLANK_NORMAL: | 591 | case FB_BLANK_NORMAL: |
579 | pr_debug("fb%d: blank\n", info->node); | 592 | pr_debug("fb%d: blank\n", info->node); |
580 | svga_wcrt_mask(0x36, 0x00, 0x30); | 593 | svga_wcrt_mask(par->state.vgabase, 0x36, 0x00, 0x30); |
581 | svga_wseq_mask(0x01, 0x20, 0x20); | 594 | svga_wseq_mask(par->state.vgabase, 0x01, 0x20, 0x20); |
582 | break; | 595 | break; |
583 | case FB_BLANK_HSYNC_SUSPEND: | 596 | case FB_BLANK_HSYNC_SUSPEND: |
584 | pr_debug("fb%d: DPMS standby (hsync off)\n", info->node); | 597 | pr_debug("fb%d: DPMS standby (hsync off)\n", info->node); |
585 | svga_wcrt_mask(0x36, 0x10, 0x30); | 598 | svga_wcrt_mask(par->state.vgabase, 0x36, 0x10, 0x30); |
586 | svga_wseq_mask(0x01, 0x20, 0x20); | 599 | svga_wseq_mask(par->state.vgabase, 0x01, 0x20, 0x20); |
587 | break; | 600 | break; |
588 | case FB_BLANK_VSYNC_SUSPEND: | 601 | case FB_BLANK_VSYNC_SUSPEND: |
589 | pr_debug("fb%d: DPMS suspend (vsync off)\n", info->node); | 602 | pr_debug("fb%d: DPMS suspend (vsync off)\n", info->node); |
590 | svga_wcrt_mask(0x36, 0x20, 0x30); | 603 | svga_wcrt_mask(par->state.vgabase, 0x36, 0x20, 0x30); |
591 | svga_wseq_mask(0x01, 0x20, 0x20); | 604 | svga_wseq_mask(par->state.vgabase, 0x01, 0x20, 0x20); |
592 | break; | 605 | break; |
593 | case FB_BLANK_POWERDOWN: | 606 | case FB_BLANK_POWERDOWN: |
594 | pr_debug("fb%d: DPMS off (no sync)\n", info->node); | 607 | pr_debug("fb%d: DPMS off (no sync)\n", info->node); |
595 | svga_wcrt_mask(0x36, 0x30, 0x30); | 608 | svga_wcrt_mask(par->state.vgabase, 0x36, 0x30, 0x30); |
596 | svga_wseq_mask(0x01, 0x20, 0x20); | 609 | svga_wseq_mask(par->state.vgabase, 0x01, 0x20, 0x20); |
597 | break; | 610 | break; |
598 | } | 611 | } |
599 | 612 | ||
@@ -603,6 +616,7 @@ static int vt8623fb_blank(int blank_mode, struct fb_info *info) | |||
603 | 616 | ||
604 | static int vt8623fb_pan_display(struct fb_var_screeninfo *var, struct fb_info *info) | 617 | static int vt8623fb_pan_display(struct fb_var_screeninfo *var, struct fb_info *info) |
605 | { | 618 | { |
619 | struct vt8623fb_info *par = info->par; | ||
606 | unsigned int offset; | 620 | unsigned int offset; |
607 | 621 | ||
608 | /* Calculate the offset */ | 622 | /* Calculate the offset */ |
@@ -616,7 +630,7 @@ static int vt8623fb_pan_display(struct fb_var_screeninfo *var, struct fb_info *i | |||
616 | } | 630 | } |
617 | 631 | ||
618 | /* Set the offset */ | 632 | /* Set the offset */ |
619 | svga_wcrt_multi(vt8623_start_address_regs, offset); | 633 | svga_wcrt_multi(par->state.vgabase, vt8623_start_address_regs, offset); |
620 | 634 | ||
621 | return 0; | 635 | return 0; |
622 | } | 636 | } |
@@ -647,6 +661,8 @@ static struct fb_ops vt8623fb_ops = { | |||
647 | 661 | ||
648 | static int __devinit vt8623_pci_probe(struct pci_dev *dev, const struct pci_device_id *id) | 662 | static int __devinit vt8623_pci_probe(struct pci_dev *dev, const struct pci_device_id *id) |
649 | { | 663 | { |
664 | struct pci_bus_region bus_reg; | ||
665 | struct resource vga_res; | ||
650 | struct fb_info *info; | 666 | struct fb_info *info; |
651 | struct vt8623fb_info *par; | 667 | struct vt8623fb_info *par; |
652 | unsigned int memsize1, memsize2; | 668 | unsigned int memsize1, memsize2; |
@@ -705,9 +721,18 @@ static int __devinit vt8623_pci_probe(struct pci_dev *dev, const struct pci_devi | |||
705 | goto err_iomap_2; | 721 | goto err_iomap_2; |
706 | } | 722 | } |
707 | 723 | ||
724 | bus_reg.start = 0; | ||
725 | bus_reg.end = 64 * 1024; | ||
726 | |||
727 | vga_res.flags = IORESOURCE_IO; | ||
728 | |||
729 | pcibios_bus_to_resource(dev, &vga_res, &bus_reg); | ||
730 | |||
731 | par->state.vgabase = (void __iomem *) vga_res.start; | ||
732 | |||
708 | /* Find how many physical memory there is on card */ | 733 | /* Find how many physical memory there is on card */ |
709 | memsize1 = (vga_rseq(NULL, 0x34) + 1) >> 1; | 734 | memsize1 = (vga_rseq(par->state.vgabase, 0x34) + 1) >> 1; |
710 | memsize2 = vga_rseq(NULL, 0x39) << 2; | 735 | memsize2 = vga_rseq(par->state.vgabase, 0x39) << 2; |
711 | 736 | ||
712 | if ((16 <= memsize1) && (memsize1 <= 64) && (memsize1 == memsize2)) | 737 | if ((16 <= memsize1) && (memsize1 <= 64) && (memsize1 == memsize2)) |
713 | info->screen_size = memsize1 << 20; | 738 | info->screen_size = memsize1 << 20; |