aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/video/s3c2410fb.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/video/s3c2410fb.c')
-rw-r--r--drivers/video/s3c2410fb.c186
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
105static 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
109static int debug = 1; 104static int debug = 1;
@@ -122,17 +117,16 @@ static int debug = 0;
122static void s3c2410fb_set_lcdaddr(struct fb_info *info) 117static 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
627static int s3c2410fb_debug_store(struct device *dev, 625static 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 = {
673static int __init s3c2410fb_map_video_memory(struct fb_info *info) 668static 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
702static inline void s3c2410fb_unmap_video_memory(struct s3c2410fb_info *fbi) 694static 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
708static inline void modify_gpio(void __iomem *reg, 702static inline void modify_gpio(void __iomem *reg,
@@ -720,6 +714,7 @@ static inline void modify_gpio(void __iomem *reg,
720static int s3c2410fb_init_registers(struct fb_info *info) 714static 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
981free_video_memory: 939free_video_memory:
982 s3c2410fb_unmap_video_memory(info); 940 s3c2410fb_unmap_video_memory(fbinfo);
983release_clock: 941release_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);
993dealloc_fb: 951dealloc_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
1094int __devinit s3c2410fb_init(void) 1058int __init s3c2410fb_init(void)
1095{ 1059{
1096 return platform_driver_register(&s3c2410fb_driver); 1060 return platform_driver_register(&s3c2410fb_driver);
1097} 1061}