diff options
Diffstat (limited to 'drivers/video/sm501fb.c')
-rw-r--r-- | drivers/video/sm501fb.c | 279 |
1 files changed, 189 insertions, 90 deletions
diff --git a/drivers/video/sm501fb.c b/drivers/video/sm501fb.c index bcb44a594ebc..56ef6b3a9851 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 |
@@ -244,7 +265,7 @@ static unsigned long sm501fb_ps_to_hz(unsigned long psvalue) | |||
244 | return (unsigned long)numerator; | 265 | return (unsigned long)numerator; |
245 | } | 266 | } |
246 | 267 | ||
247 | /* sm501fb_hz_to_ps is identical to the oposite transform */ | 268 | /* sm501fb_hz_to_ps is identical to the opposite transform */ |
248 | 269 | ||
249 | #define sm501fb_hz_to_ps(x) sm501fb_ps_to_hz(x) | 270 | #define sm501fb_hz_to_ps(x) sm501fb_ps_to_hz(x) |
250 | 271 | ||
@@ -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 | ||
@@ -1690,7 +1719,7 @@ static int sm501fb_init_fb(struct fb_info *fb, | |||
1690 | (head == HEAD_CRT) ? &sm501fb_ops_crt : &sm501fb_ops_pnl, | 1719 | (head == HEAD_CRT) ? &sm501fb_ops_crt : &sm501fb_ops_pnl, |
1691 | sizeof(struct fb_ops)); | 1720 | sizeof(struct fb_ops)); |
1692 | 1721 | ||
1693 | /* update ops dependant on what we've been passed */ | 1722 | /* update ops dependent on what we've been passed */ |
1694 | 1723 | ||
1695 | if ((pd->flags & SM501FB_FLAG_USE_HWCURSOR) == 0) | 1724 | if ((pd->flags & SM501FB_FLAG_USE_HWCURSOR) == 0) |
1696 | par->ops.fb_cursor = NULL; | 1725 | par->ops.fb_cursor = NULL; |
@@ -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"); |