diff options
Diffstat (limited to 'drivers/video/s3c2410fb.c')
-rw-r--r-- | drivers/video/s3c2410fb.c | 186 |
1 files changed, 75 insertions, 111 deletions
diff --git a/drivers/video/s3c2410fb.c b/drivers/video/s3c2410fb.c index 2ecf7717491f..09d19633d3bc 100644 --- a/drivers/video/s3c2410fb.c +++ b/drivers/video/s3c2410fb.c | |||
@@ -20,7 +20,7 @@ | |||
20 | * | 20 | * |
21 | * 2004-12-04: Arnaud Patard <arnaud.patard@rtp-net.org> | 21 | * 2004-12-04: Arnaud Patard <arnaud.patard@rtp-net.org> |
22 | * - Added the possibility to set on or off the | 22 | * - Added the possibility to set on or off the |
23 | * debugging mesaages | 23 | * debugging messages |
24 | * - Replaced 0 and 1 by on or off when reading the | 24 | * - Replaced 0 and 1 by on or off when reading the |
25 | * /sys files | 25 | * /sys files |
26 | * | 26 | * |
@@ -31,7 +31,7 @@ | |||
31 | * - add pixel clock divisor control | 31 | * - add pixel clock divisor control |
32 | * | 32 | * |
33 | * 2004-11-11: Arnaud Patard <arnaud.patard@rtp-net.org> | 33 | * 2004-11-11: Arnaud Patard <arnaud.patard@rtp-net.org> |
34 | * - Removed the use of currcon as it no more exist | 34 | * - Removed the use of currcon as it no more exists |
35 | * - Added LCD power sysfs interface | 35 | * - Added LCD power sysfs interface |
36 | * | 36 | * |
37 | * 2004-11-03: Ben Dooks <ben-linux@fluff.org> | 37 | * 2004-11-03: Ben Dooks <ben-linux@fluff.org> |
@@ -82,13 +82,10 @@ | |||
82 | #include <linux/init.h> | 82 | #include <linux/init.h> |
83 | #include <linux/dma-mapping.h> | 83 | #include <linux/dma-mapping.h> |
84 | #include <linux/interrupt.h> | 84 | #include <linux/interrupt.h> |
85 | #include <linux/workqueue.h> | ||
86 | #include <linux/wait.h> | ||
87 | #include <linux/platform_device.h> | 85 | #include <linux/platform_device.h> |
88 | #include <linux/clk.h> | 86 | #include <linux/clk.h> |
89 | 87 | ||
90 | #include <asm/io.h> | 88 | #include <asm/io.h> |
91 | #include <asm/uaccess.h> | ||
92 | #include <asm/div64.h> | 89 | #include <asm/div64.h> |
93 | 90 | ||
94 | #include <asm/mach/map.h> | 91 | #include <asm/mach/map.h> |
@@ -102,8 +99,6 @@ | |||
102 | 99 | ||
103 | #include "s3c2410fb.h" | 100 | #include "s3c2410fb.h" |
104 | 101 | ||
105 | static struct s3c2410fb_mach_info *mach_info; | ||
106 | |||
107 | /* Debugging stuff */ | 102 | /* Debugging stuff */ |
108 | #ifdef CONFIG_FB_S3C2410_DEBUG | 103 | #ifdef CONFIG_FB_S3C2410_DEBUG |
109 | static int debug = 1; | 104 | static int debug = 1; |
@@ -122,17 +117,16 @@ static int debug = 0; | |||
122 | static void s3c2410fb_set_lcdaddr(struct fb_info *info) | 117 | static void s3c2410fb_set_lcdaddr(struct fb_info *info) |
123 | { | 118 | { |
124 | unsigned long saddr1, saddr2, saddr3; | 119 | unsigned long saddr1, saddr2, saddr3; |
125 | int line_length = info->var.xres * info->var.bits_per_pixel; | ||
126 | struct s3c2410fb_info *fbi = info->par; | 120 | struct s3c2410fb_info *fbi = info->par; |
127 | void __iomem *regs = fbi->io; | 121 | void __iomem *regs = fbi->io; |
128 | 122 | ||
129 | saddr1 = info->fix.smem_start >> 1; | 123 | saddr1 = info->fix.smem_start >> 1; |
130 | saddr2 = info->fix.smem_start; | 124 | saddr2 = info->fix.smem_start; |
131 | saddr2 += (line_length * info->var.yres) / 8; | 125 | saddr2 += info->fix.line_length * info->var.yres; |
132 | saddr2 >>= 1; | 126 | saddr2 >>= 1; |
133 | 127 | ||
134 | saddr3 = S3C2410_OFFSIZE(0) | | 128 | saddr3 = S3C2410_OFFSIZE(0) | |
135 | S3C2410_PAGEWIDTH((line_length / 16) & 0x3ff); | 129 | S3C2410_PAGEWIDTH((info->fix.line_length / 2) & 0x3ff); |
136 | 130 | ||
137 | dprintk("LCDSADDR1 = 0x%08lx\n", saddr1); | 131 | dprintk("LCDSADDR1 = 0x%08lx\n", saddr1); |
138 | dprintk("LCDSADDR2 = 0x%08lx\n", saddr2); | 132 | dprintk("LCDSADDR2 = 0x%08lx\n", saddr2); |
@@ -153,14 +147,14 @@ static unsigned int s3c2410fb_calc_pixclk(struct s3c2410fb_info *fbi, | |||
153 | unsigned long clk = clk_get_rate(fbi->clk); | 147 | unsigned long clk = clk_get_rate(fbi->clk); |
154 | unsigned long long div; | 148 | unsigned long long div; |
155 | 149 | ||
156 | /* pixclk is in picoseoncds, our clock is in Hz | 150 | /* pixclk is in picoseconds, our clock is in Hz |
157 | * | 151 | * |
158 | * Hz -> picoseconds is / 10^-12 | 152 | * Hz -> picoseconds is / 10^-12 |
159 | */ | 153 | */ |
160 | 154 | ||
161 | div = (unsigned long long)clk * pixclk; | 155 | div = (unsigned long long)clk * pixclk; |
162 | do_div(div, 1000000UL); | 156 | div >>= 12; /* div / 2^12 */ |
163 | do_div(div, 1000000UL); | 157 | do_div(div, 625 * 625UL * 625); /* div / 5^12 */ |
164 | 158 | ||
165 | dprintk("pixclk %ld, divisor is %ld\n", pixclk, (long)div); | 159 | dprintk("pixclk %ld, divisor is %ld\n", pixclk, (long)div); |
166 | return div; | 160 | return div; |
@@ -176,7 +170,7 @@ static int s3c2410fb_check_var(struct fb_var_screeninfo *var, | |||
176 | struct fb_info *info) | 170 | struct fb_info *info) |
177 | { | 171 | { |
178 | struct s3c2410fb_info *fbi = info->par; | 172 | struct s3c2410fb_info *fbi = info->par; |
179 | struct s3c2410fb_mach_info *mach_info = fbi->mach_info; | 173 | struct s3c2410fb_mach_info *mach_info = fbi->dev->platform_data; |
180 | struct s3c2410fb_display *display = NULL; | 174 | struct s3c2410fb_display *display = NULL; |
181 | unsigned i; | 175 | unsigned i; |
182 | 176 | ||
@@ -189,7 +183,6 @@ static int s3c2410fb_check_var(struct fb_var_screeninfo *var, | |||
189 | var->xres == mach_info->displays[i].xres && | 183 | var->xres == mach_info->displays[i].xres && |
190 | var->bits_per_pixel == mach_info->displays[i].bpp) { | 184 | var->bits_per_pixel == mach_info->displays[i].bpp) { |
191 | display = mach_info->displays + i; | 185 | display = mach_info->displays + i; |
192 | fbi->current_display = i; | ||
193 | break; | 186 | break; |
194 | } | 187 | } |
195 | 188 | ||
@@ -202,10 +195,22 @@ static int s3c2410fb_check_var(struct fb_var_screeninfo *var, | |||
202 | /* it is always the size as the display */ | 195 | /* it is always the size as the display */ |
203 | var->xres_virtual = display->xres; | 196 | var->xres_virtual = display->xres; |
204 | var->yres_virtual = display->yres; | 197 | var->yres_virtual = display->yres; |
198 | var->height = display->height; | ||
199 | var->width = display->width; | ||
205 | 200 | ||
206 | /* copy lcd settings */ | 201 | /* copy lcd settings */ |
207 | var->left_margin = display->left_margin; | 202 | var->left_margin = display->left_margin; |
208 | var->right_margin = display->right_margin; | 203 | var->right_margin = display->right_margin; |
204 | var->upper_margin = display->upper_margin; | ||
205 | var->lower_margin = display->lower_margin; | ||
206 | var->vsync_len = display->vsync_len; | ||
207 | var->hsync_len = display->hsync_len; | ||
208 | |||
209 | fbi->regs.lcdcon1 = display->lcdcon1; | ||
210 | fbi->regs.lcdcon5 = display->lcdcon5; | ||
211 | /* set display type */ | ||
212 | fbi->regs.lcdcon1 &= ~S3C2410_LCDCON1_TFT; | ||
213 | fbi->regs.lcdcon1 |= display->type; | ||
209 | 214 | ||
210 | var->transp.offset = 0; | 215 | var->transp.offset = 0; |
211 | var->transp.length = 0; | 216 | var->transp.length = 0; |
@@ -420,19 +425,13 @@ static void s3c2410fb_activate_var(struct fb_info *info) | |||
420 | { | 425 | { |
421 | struct s3c2410fb_info *fbi = info->par; | 426 | struct s3c2410fb_info *fbi = info->par; |
422 | void __iomem *regs = fbi->io; | 427 | void __iomem *regs = fbi->io; |
428 | int type = fbi->regs.lcdcon1 & S3C2410_LCDCON1_TFT; | ||
423 | struct fb_var_screeninfo *var = &info->var; | 429 | struct fb_var_screeninfo *var = &info->var; |
424 | struct s3c2410fb_mach_info *mach_info = fbi->mach_info; | ||
425 | struct s3c2410fb_display *display = mach_info->displays + | ||
426 | fbi->current_display; | ||
427 | |||
428 | /* set display type */ | ||
429 | fbi->regs.lcdcon1 &= ~S3C2410_LCDCON1_TFT; | ||
430 | fbi->regs.lcdcon1 |= display->type; | ||
431 | 430 | ||
432 | if (var->pixclock > 0) { | 431 | if (var->pixclock > 0) { |
433 | int clkdiv = s3c2410fb_calc_pixclk(fbi, var->pixclock); | 432 | int clkdiv = s3c2410fb_calc_pixclk(fbi, var->pixclock); |
434 | 433 | ||
435 | if (display->type == S3C2410_LCDCON1_TFT) { | 434 | if (type == S3C2410_LCDCON1_TFT) { |
436 | clkdiv = (clkdiv / 2) - 1; | 435 | clkdiv = (clkdiv / 2) - 1; |
437 | if (clkdiv < 0) | 436 | if (clkdiv < 0) |
438 | clkdiv = 0; | 437 | clkdiv = 0; |
@@ -446,7 +445,7 @@ static void s3c2410fb_activate_var(struct fb_info *info) | |||
446 | fbi->regs.lcdcon1 |= S3C2410_LCDCON1_CLKVAL(clkdiv); | 445 | fbi->regs.lcdcon1 |= S3C2410_LCDCON1_CLKVAL(clkdiv); |
447 | } | 446 | } |
448 | 447 | ||
449 | if (display->type == S3C2410_LCDCON1_TFT) | 448 | if (type == S3C2410_LCDCON1_TFT) |
450 | s3c2410fb_calculate_tft_lcd_regs(info, &fbi->regs); | 449 | s3c2410fb_calculate_tft_lcd_regs(info, &fbi->regs); |
451 | else | 450 | else |
452 | s3c2410fb_calculate_stn_lcd_regs(info, &fbi->regs); | 451 | s3c2410fb_calculate_stn_lcd_regs(info, &fbi->regs); |
@@ -470,6 +469,7 @@ static void s3c2410fb_activate_var(struct fb_info *info) | |||
470 | /* set lcd address pointers */ | 469 | /* set lcd address pointers */ |
471 | s3c2410fb_set_lcdaddr(info); | 470 | s3c2410fb_set_lcdaddr(info); |
472 | 471 | ||
472 | fbi->regs.lcdcon1 |= S3C2410_LCDCON1_ENVID, | ||
473 | writel(fbi->regs.lcdcon1, regs + S3C2410_LCDCON1); | 473 | writel(fbi->regs.lcdcon1, regs + S3C2410_LCDCON1); |
474 | } | 474 | } |
475 | 475 | ||
@@ -566,9 +566,9 @@ static int s3c2410fb_setcolreg(unsigned regno, | |||
566 | if (regno < 256) { | 566 | if (regno < 256) { |
567 | /* currently assume RGB 5-6-5 mode */ | 567 | /* currently assume RGB 5-6-5 mode */ |
568 | 568 | ||
569 | val = ((red >> 0) & 0xf800); | 569 | val = (red >> 0) & 0xf800; |
570 | val |= ((green >> 5) & 0x07e0); | 570 | val |= (green >> 5) & 0x07e0; |
571 | val |= ((blue >> 11) & 0x001f); | 571 | val |= (blue >> 11) & 0x001f; |
572 | 572 | ||
573 | writel(val, regs + S3C2410_TFTPAL(regno)); | 573 | writel(val, regs + S3C2410_TFTPAL(regno)); |
574 | schedule_palette_update(fbi, regno, val); | 574 | schedule_palette_update(fbi, regno, val); |
@@ -606,9 +606,6 @@ static int s3c2410fb_blank(int blank_mode, struct fb_info *info) | |||
606 | 606 | ||
607 | dprintk("blank(mode=%d, info=%p)\n", blank_mode, info); | 607 | dprintk("blank(mode=%d, info=%p)\n", blank_mode, info); |
608 | 608 | ||
609 | if (mach_info == NULL) | ||
610 | return -EINVAL; | ||
611 | |||
612 | if (blank_mode == FB_BLANK_UNBLANK) | 609 | if (blank_mode == FB_BLANK_UNBLANK) |
613 | writel(0x0, regs + S3C2410_TPAL); | 610 | writel(0x0, regs + S3C2410_TPAL); |
614 | else { | 611 | else { |
@@ -624,13 +621,11 @@ static int s3c2410fb_debug_show(struct device *dev, | |||
624 | { | 621 | { |
625 | return snprintf(buf, PAGE_SIZE, "%s\n", debug ? "on" : "off"); | 622 | return snprintf(buf, PAGE_SIZE, "%s\n", debug ? "on" : "off"); |
626 | } | 623 | } |
624 | |||
627 | static int s3c2410fb_debug_store(struct device *dev, | 625 | static int s3c2410fb_debug_store(struct device *dev, |
628 | struct device_attribute *attr, | 626 | struct device_attribute *attr, |
629 | const char *buf, size_t len) | 627 | const char *buf, size_t len) |
630 | { | 628 | { |
631 | if (mach_info == NULL) | ||
632 | return -EINVAL; | ||
633 | |||
634 | if (len < 1) | 629 | if (len < 1) |
635 | return -EINVAL; | 630 | return -EINVAL; |
636 | 631 | ||
@@ -673,36 +668,35 @@ static struct fb_ops s3c2410fb_ops = { | |||
673 | static int __init s3c2410fb_map_video_memory(struct fb_info *info) | 668 | static int __init s3c2410fb_map_video_memory(struct fb_info *info) |
674 | { | 669 | { |
675 | struct s3c2410fb_info *fbi = info->par; | 670 | struct s3c2410fb_info *fbi = info->par; |
671 | dma_addr_t map_dma; | ||
672 | unsigned map_size = PAGE_ALIGN(info->fix.smem_len); | ||
676 | 673 | ||
677 | dprintk("map_video_memory(fbi=%p)\n", fbi); | 674 | dprintk("map_video_memory(fbi=%p)\n", fbi); |
678 | 675 | ||
679 | fbi->map_size = PAGE_ALIGN(info->fix.smem_len + PAGE_SIZE); | 676 | info->screen_base = dma_alloc_writecombine(fbi->dev, map_size, |
680 | fbi->map_cpu = dma_alloc_writecombine(fbi->dev, fbi->map_size, | 677 | &map_dma, GFP_KERNEL); |
681 | &fbi->map_dma, GFP_KERNEL); | ||
682 | 678 | ||
683 | fbi->map_size = info->fix.smem_len; | 679 | if (info->screen_base) { |
684 | |||
685 | if (fbi->map_cpu) { | ||
686 | /* prevent initial garbage on screen */ | 680 | /* prevent initial garbage on screen */ |
687 | dprintk("map_video_memory: clear %p:%08x\n", | 681 | dprintk("map_video_memory: clear %p:%08x\n", |
688 | fbi->map_cpu, fbi->map_size); | 682 | info->screen_base, map_size); |
689 | memset(fbi->map_cpu, 0xf0, fbi->map_size); | 683 | memset(info->screen_base, 0xf0, map_size); |
690 | 684 | ||
691 | fbi->screen_dma = fbi->map_dma; | 685 | info->fix.smem_start = map_dma; |
692 | info->screen_base = fbi->map_cpu; | ||
693 | info->fix.smem_start = fbi->screen_dma; | ||
694 | 686 | ||
695 | dprintk("map_video_memory: dma=%08x cpu=%p size=%08x\n", | 687 | dprintk("map_video_memory: dma=%08lx cpu=%p size=%08x\n", |
696 | fbi->map_dma, fbi->map_cpu, info->fix.smem_len); | 688 | info->fix.smem_start, info->screen_base, map_size); |
697 | } | 689 | } |
698 | 690 | ||
699 | return fbi->map_cpu ? 0 : -ENOMEM; | 691 | return info->screen_base ? 0 : -ENOMEM; |
700 | } | 692 | } |
701 | 693 | ||
702 | static inline void s3c2410fb_unmap_video_memory(struct s3c2410fb_info *fbi) | 694 | static inline void s3c2410fb_unmap_video_memory(struct fb_info *info) |
703 | { | 695 | { |
704 | dma_free_writecombine(fbi->dev, fbi->map_size, fbi->map_cpu, | 696 | struct s3c2410fb_info *fbi = info->par; |
705 | fbi->map_dma); | 697 | |
698 | dma_free_writecombine(fbi->dev, PAGE_ALIGN(info->fix.smem_len), | ||
699 | info->screen_base, info->fix.smem_start); | ||
706 | } | 700 | } |
707 | 701 | ||
708 | static inline void modify_gpio(void __iomem *reg, | 702 | static inline void modify_gpio(void __iomem *reg, |
@@ -720,6 +714,7 @@ static inline void modify_gpio(void __iomem *reg, | |||
720 | static int s3c2410fb_init_registers(struct fb_info *info) | 714 | static int s3c2410fb_init_registers(struct fb_info *info) |
721 | { | 715 | { |
722 | struct s3c2410fb_info *fbi = info->par; | 716 | struct s3c2410fb_info *fbi = info->par; |
717 | struct s3c2410fb_mach_info *mach_info = fbi->dev->platform_data; | ||
723 | unsigned long flags; | 718 | unsigned long flags; |
724 | void __iomem *regs = fbi->io; | 719 | void __iomem *regs = fbi->io; |
725 | 720 | ||
@@ -736,14 +731,6 @@ static int s3c2410fb_init_registers(struct fb_info *info) | |||
736 | 731 | ||
737 | local_irq_restore(flags); | 732 | local_irq_restore(flags); |
738 | 733 | ||
739 | writel(fbi->regs.lcdcon1, regs + S3C2410_LCDCON1); | ||
740 | writel(fbi->regs.lcdcon2, regs + S3C2410_LCDCON2); | ||
741 | writel(fbi->regs.lcdcon3, regs + S3C2410_LCDCON3); | ||
742 | writel(fbi->regs.lcdcon4, regs + S3C2410_LCDCON4); | ||
743 | writel(fbi->regs.lcdcon5, regs + S3C2410_LCDCON5); | ||
744 | |||
745 | s3c2410fb_set_lcdaddr(info); | ||
746 | |||
747 | dprintk("LPCSEL = 0x%08lx\n", mach_info->lpcsel); | 734 | dprintk("LPCSEL = 0x%08lx\n", mach_info->lpcsel); |
748 | writel(mach_info->lpcsel, regs + S3C2410_LPCSEL); | 735 | writel(mach_info->lpcsel, regs + S3C2410_LPCSEL); |
749 | 736 | ||
@@ -752,9 +739,6 @@ static int s3c2410fb_init_registers(struct fb_info *info) | |||
752 | /* ensure temporary palette disabled */ | 739 | /* ensure temporary palette disabled */ |
753 | writel(0x00, regs + S3C2410_TPAL); | 740 | writel(0x00, regs + S3C2410_TPAL); |
754 | 741 | ||
755 | /* Enable video by setting the ENVID bit to 1 */ | ||
756 | fbi->regs.lcdcon1 |= S3C2410_LCDCON1_ENVID; | ||
757 | writel(fbi->regs.lcdcon1, regs + S3C2410_LCDCON1); | ||
758 | return 0; | 742 | return 0; |
759 | } | 743 | } |
760 | 744 | ||
@@ -808,6 +792,7 @@ static int __init s3c2410fb_probe(struct platform_device *pdev) | |||
808 | struct s3c2410fb_info *info; | 792 | struct s3c2410fb_info *info; |
809 | struct s3c2410fb_display *display; | 793 | struct s3c2410fb_display *display; |
810 | struct fb_info *fbinfo; | 794 | struct fb_info *fbinfo; |
795 | struct s3c2410fb_mach_info *mach_info; | ||
811 | struct resource *res; | 796 | struct resource *res; |
812 | int ret; | 797 | int ret; |
813 | int irq; | 798 | int irq; |
@@ -834,6 +819,8 @@ static int __init s3c2410fb_probe(struct platform_device *pdev) | |||
834 | if (!fbinfo) | 819 | if (!fbinfo) |
835 | return -ENOMEM; | 820 | return -ENOMEM; |
836 | 821 | ||
822 | platform_set_drvdata(pdev, fbinfo); | ||
823 | |||
837 | info = fbinfo->par; | 824 | info = fbinfo->par; |
838 | info->dev = &pdev->dev; | 825 | info->dev = &pdev->dev; |
839 | 826 | ||
@@ -859,23 +846,14 @@ static int __init s3c2410fb_probe(struct platform_device *pdev) | |||
859 | goto release_mem; | 846 | goto release_mem; |
860 | } | 847 | } |
861 | 848 | ||
862 | platform_set_drvdata(pdev, fbinfo); | ||
863 | |||
864 | dprintk("devinit\n"); | 849 | dprintk("devinit\n"); |
865 | 850 | ||
866 | strcpy(fbinfo->fix.id, driver_name); | 851 | strcpy(fbinfo->fix.id, driver_name); |
867 | 852 | ||
868 | info->regs.lcdcon1 = display->lcdcon1; | 853 | /* Stop the video */ |
869 | info->regs.lcdcon5 = display->lcdcon5; | ||
870 | |||
871 | /* Stop the video and unset ENVID if set */ | ||
872 | info->regs.lcdcon1 &= ~S3C2410_LCDCON1_ENVID; | ||
873 | lcdcon1 = readl(info->io + S3C2410_LCDCON1); | 854 | lcdcon1 = readl(info->io + S3C2410_LCDCON1); |
874 | writel(lcdcon1 & ~S3C2410_LCDCON1_ENVID, info->io + S3C2410_LCDCON1); | 855 | writel(lcdcon1 & ~S3C2410_LCDCON1_ENVID, info->io + S3C2410_LCDCON1); |
875 | 856 | ||
876 | info->mach_info = pdev->dev.platform_data; | ||
877 | info->current_display = mach_info->default_display; | ||
878 | |||
879 | fbinfo->fix.type = FB_TYPE_PACKED_PIXELS; | 857 | fbinfo->fix.type = FB_TYPE_PACKED_PIXELS; |
880 | fbinfo->fix.type_aux = 0; | 858 | fbinfo->fix.type_aux = 0; |
881 | fbinfo->fix.xpanstep = 0; | 859 | fbinfo->fix.xpanstep = 0; |
@@ -885,8 +863,6 @@ static int __init s3c2410fb_probe(struct platform_device *pdev) | |||
885 | 863 | ||
886 | fbinfo->var.nonstd = 0; | 864 | fbinfo->var.nonstd = 0; |
887 | fbinfo->var.activate = FB_ACTIVATE_NOW; | 865 | fbinfo->var.activate = FB_ACTIVATE_NOW; |
888 | fbinfo->var.height = display->height; | ||
889 | fbinfo->var.width = display->width; | ||
890 | fbinfo->var.accel_flags = 0; | 866 | fbinfo->var.accel_flags = 0; |
891 | fbinfo->var.vmode = FB_VMODE_NONINTERLACED; | 867 | fbinfo->var.vmode = FB_VMODE_NONINTERLACED; |
892 | 868 | ||
@@ -894,39 +870,6 @@ static int __init s3c2410fb_probe(struct platform_device *pdev) | |||
894 | fbinfo->flags = FBINFO_FLAG_DEFAULT; | 870 | fbinfo->flags = FBINFO_FLAG_DEFAULT; |
895 | fbinfo->pseudo_palette = &info->pseudo_pal; | 871 | fbinfo->pseudo_palette = &info->pseudo_pal; |
896 | 872 | ||
897 | fbinfo->var.xres = display->xres; | ||
898 | fbinfo->var.xres_virtual = display->xres; | ||
899 | fbinfo->var.yres = display->yres; | ||
900 | fbinfo->var.yres_virtual = display->yres; | ||
901 | fbinfo->var.bits_per_pixel = display->bpp; | ||
902 | fbinfo->var.left_margin = display->left_margin; | ||
903 | fbinfo->var.right_margin = display->right_margin; | ||
904 | |||
905 | fbinfo->var.upper_margin = display->upper_margin; | ||
906 | fbinfo->var.lower_margin = display->lower_margin; | ||
907 | fbinfo->var.vsync_len = display->vsync_len; | ||
908 | fbinfo->var.hsync_len = display->hsync_len; | ||
909 | |||
910 | fbinfo->var.red.offset = 11; | ||
911 | fbinfo->var.green.offset = 5; | ||
912 | fbinfo->var.blue.offset = 0; | ||
913 | fbinfo->var.transp.offset = 0; | ||
914 | fbinfo->var.red.length = 5; | ||
915 | fbinfo->var.green.length = 6; | ||
916 | fbinfo->var.blue.length = 5; | ||
917 | fbinfo->var.transp.length = 0; | ||
918 | |||
919 | /* find maximum required memory size for display */ | ||
920 | for (i = 0; i < mach_info->num_displays; i++) { | ||
921 | unsigned long smem_len = mach_info->displays[i].xres; | ||
922 | |||
923 | smem_len *= mach_info->displays[i].yres; | ||
924 | smem_len *= mach_info->displays[i].bpp; | ||
925 | smem_len >>= 3; | ||
926 | if (fbinfo->fix.smem_len < smem_len) | ||
927 | fbinfo->fix.smem_len = smem_len; | ||
928 | } | ||
929 | |||
930 | for (i = 0; i < 256; i++) | 873 | for (i = 0; i < 256; i++) |
931 | info->palette_buffer[i] = PALETTE_BUFF_CLEAR; | 874 | info->palette_buffer[i] = PALETTE_BUFF_CLEAR; |
932 | 875 | ||
@@ -949,6 +892,17 @@ static int __init s3c2410fb_probe(struct platform_device *pdev) | |||
949 | 892 | ||
950 | msleep(1); | 893 | msleep(1); |
951 | 894 | ||
895 | /* find maximum required memory size for display */ | ||
896 | for (i = 0; i < mach_info->num_displays; i++) { | ||
897 | unsigned long smem_len = mach_info->displays[i].xres; | ||
898 | |||
899 | smem_len *= mach_info->displays[i].yres; | ||
900 | smem_len *= mach_info->displays[i].bpp; | ||
901 | smem_len >>= 3; | ||
902 | if (fbinfo->fix.smem_len < smem_len) | ||
903 | fbinfo->fix.smem_len = smem_len; | ||
904 | } | ||
905 | |||
952 | /* Initialize video memory */ | 906 | /* Initialize video memory */ |
953 | ret = s3c2410fb_map_video_memory(fbinfo); | 907 | ret = s3c2410fb_map_video_memory(fbinfo); |
954 | if (ret) { | 908 | if (ret) { |
@@ -959,6 +913,10 @@ static int __init s3c2410fb_probe(struct platform_device *pdev) | |||
959 | 913 | ||
960 | dprintk("got video memory\n"); | 914 | dprintk("got video memory\n"); |
961 | 915 | ||
916 | fbinfo->var.xres = display->xres; | ||
917 | fbinfo->var.yres = display->yres; | ||
918 | fbinfo->var.bits_per_pixel = display->bpp; | ||
919 | |||
962 | s3c2410fb_init_registers(fbinfo); | 920 | s3c2410fb_init_registers(fbinfo); |
963 | 921 | ||
964 | s3c2410fb_check_var(&fbinfo->var, fbinfo); | 922 | s3c2410fb_check_var(&fbinfo->var, fbinfo); |
@@ -979,7 +937,7 @@ static int __init s3c2410fb_probe(struct platform_device *pdev) | |||
979 | return 0; | 937 | return 0; |
980 | 938 | ||
981 | free_video_memory: | 939 | free_video_memory: |
982 | s3c2410fb_unmap_video_memory(info); | 940 | s3c2410fb_unmap_video_memory(fbinfo); |
983 | release_clock: | 941 | release_clock: |
984 | clk_disable(info->clk); | 942 | clk_disable(info->clk); |
985 | clk_put(info->clk); | 943 | clk_put(info->clk); |
@@ -991,6 +949,7 @@ release_mem: | |||
991 | release_resource(info->mem); | 949 | release_resource(info->mem); |
992 | kfree(info->mem); | 950 | kfree(info->mem); |
993 | dealloc_fb: | 951 | dealloc_fb: |
952 | platform_set_drvdata(pdev, NULL); | ||
994 | framebuffer_release(fbinfo); | 953 | framebuffer_release(fbinfo); |
995 | return ret; | 954 | return ret; |
996 | } | 955 | } |
@@ -1020,10 +979,12 @@ static int s3c2410fb_remove(struct platform_device *pdev) | |||
1020 | struct s3c2410fb_info *info = fbinfo->par; | 979 | struct s3c2410fb_info *info = fbinfo->par; |
1021 | int irq; | 980 | int irq; |
1022 | 981 | ||
982 | unregister_framebuffer(fbinfo); | ||
983 | |||
1023 | s3c2410fb_stop_lcd(info); | 984 | s3c2410fb_stop_lcd(info); |
1024 | msleep(1); | 985 | msleep(1); |
1025 | 986 | ||
1026 | s3c2410fb_unmap_video_memory(info); | 987 | s3c2410fb_unmap_video_memory(fbinfo); |
1027 | 988 | ||
1028 | if (info->clk) { | 989 | if (info->clk) { |
1029 | clk_disable(info->clk); | 990 | clk_disable(info->clk); |
@@ -1034,10 +995,13 @@ static int s3c2410fb_remove(struct platform_device *pdev) | |||
1034 | irq = platform_get_irq(pdev, 0); | 995 | irq = platform_get_irq(pdev, 0); |
1035 | free_irq(irq, info); | 996 | free_irq(irq, info); |
1036 | 997 | ||
998 | iounmap(info->io); | ||
999 | |||
1037 | release_resource(info->mem); | 1000 | release_resource(info->mem); |
1038 | kfree(info->mem); | 1001 | kfree(info->mem); |
1039 | iounmap(info->io); | 1002 | |
1040 | unregister_framebuffer(fbinfo); | 1003 | platform_set_drvdata(pdev, NULL); |
1004 | framebuffer_release(fbinfo); | ||
1041 | 1005 | ||
1042 | return 0; | 1006 | return 0; |
1043 | } | 1007 | } |
@@ -1091,7 +1055,7 @@ static struct platform_driver s3c2410fb_driver = { | |||
1091 | }, | 1055 | }, |
1092 | }; | 1056 | }; |
1093 | 1057 | ||
1094 | int __devinit s3c2410fb_init(void) | 1058 | int __init s3c2410fb_init(void) |
1095 | { | 1059 | { |
1096 | return platform_driver_register(&s3c2410fb_driver); | 1060 | return platform_driver_register(&s3c2410fb_driver); |
1097 | } | 1061 | } |