3 * Copyright (c) 2009 Nuvoton technology corporation
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
12 * Nuvoton LCD Controller Driver
14 * Wang Qiang (rurality.linux@gmail.com) 2009/12/11
16 #include <linux/module.h>
17 #include <linux/kernel.h>
18 #include <linux/err.h>
19 #include <linux/errno.h>
20 #include <linux/string.h>
22 #include <linux/tty.h>
23 #include <linux/slab.h>
24 #include <linux/delay.h>
26 #include <linux/init.h>
27 #include <linux/dma-mapping.h>
28 #include <linux/interrupt.h>
29 #include <linux/workqueue.h>
30 #include <linux/wait.h>
31 #include <linux/platform_device.h>
32 #include <linux/clk.h>
33 #include <linux/cpufreq.h>
36 #include <linux/device.h>
39 #include <mach/regs-clock.h>
40 #include <mach/regs-ldm.h>
42 #include <mach/clkdev.h>
48 * Initialize the nuc900 video (dual) buffer address
50 static void nuc900fb_set_lcdaddr(struct fb_info
*info
)
52 struct nuc900fb_info
*fbi
= info
->par
;
53 void __iomem
*regs
= fbi
->io
;
54 unsigned long vbaddr1
, vbaddr2
;
56 vbaddr1
= info
->fix
.smem_start
;
57 vbaddr2
= info
->fix
.smem_start
;
58 vbaddr2
+= info
->fix
.line_length
* info
->var
.yres
;
60 /* set frambuffer start phy addr*/
61 writel(vbaddr1
, regs
+ REG_LCM_VA_BADDR0
);
62 writel(vbaddr2
, regs
+ REG_LCM_VA_BADDR1
);
64 writel(fbi
->regs
.lcd_va_fbctrl
, regs
+ REG_LCM_VA_FBCTRL
);
65 writel(fbi
->regs
.lcd_va_scale
, regs
+ REG_LCM_VA_SCALE
);
69 * calculate divider for lcd div
71 static unsigned int nuc900fb_calc_pixclk(struct nuc900fb_info
*fbi
,
74 unsigned long clk
= fbi
->clk_rate
;
75 unsigned long long div
;
77 /* pixclk is in picseconds. our clock is in Hz*/
78 /* div = (clk * pixclk)/10^12 */
79 div
= (unsigned long long)clk
* pixclk
;
81 do_div(div
, 625 * 625UL * 625);
83 dev_dbg(fbi
->dev
, "pixclk %ld, divisor is %lld\n", pixclk
, div
);
89 * Check the video params of 'var'.
91 static int nuc900fb_check_var(struct fb_var_screeninfo
*var
,
94 struct nuc900fb_info
*fbi
= info
->par
;
95 struct nuc900fb_mach_info
*mach_info
= fbi
->dev
->platform_data
;
96 struct nuc900fb_display
*display
= NULL
;
97 struct nuc900fb_display
*default_display
= mach_info
->displays
+
98 mach_info
->default_display
;
101 dev_dbg(fbi
->dev
, "check_var(var=%p, info=%p)\n", var
, info
);
103 /* validate x/y resolution */
104 /* choose default mode if possible */
105 if (var
->xres
== default_display
->xres
&&
106 var
->yres
== default_display
->yres
&&
107 var
->bits_per_pixel
== default_display
->bpp
)
108 display
= default_display
;
110 for (i
= 0; i
< mach_info
->num_displays
; i
++)
111 if (var
->xres
== mach_info
->displays
[i
].xres
&&
112 var
->yres
== mach_info
->displays
[i
].yres
&&
113 var
->bits_per_pixel
== mach_info
->displays
[i
].bpp
) {
114 display
= mach_info
->displays
+ i
;
118 if (display
== NULL
) {
119 printk(KERN_ERR
"wrong resolution or depth %dx%d at %d bit per pixel\n",
120 var
->xres
, var
->yres
, var
->bits_per_pixel
);
124 /* it should be the same size as the display */
125 var
->xres_virtual
= display
->xres
;
126 var
->yres_virtual
= display
->yres
;
127 var
->height
= display
->height
;
128 var
->width
= display
->width
;
130 /* copy lcd settings */
131 var
->pixclock
= display
->pixclock
;
132 var
->left_margin
= display
->left_margin
;
133 var
->right_margin
= display
->right_margin
;
134 var
->upper_margin
= display
->upper_margin
;
135 var
->lower_margin
= display
->lower_margin
;
136 var
->vsync_len
= display
->vsync_len
;
137 var
->hsync_len
= display
->hsync_len
;
139 var
->transp
.offset
= 0;
140 var
->transp
.length
= 0;
142 fbi
->regs
.lcd_dccs
= display
->dccs
;
143 fbi
->regs
.lcd_device_ctrl
= display
->devctl
;
144 fbi
->regs
.lcd_va_fbctrl
= display
->fbctrl
;
145 fbi
->regs
.lcd_va_scale
= display
->scale
;
147 /* set R/G/B possions */
148 switch (var
->bits_per_pixel
) {
155 var
->red
.length
= var
->bits_per_pixel
;
156 var
->green
= var
->red
;
157 var
->blue
= var
->red
;
161 var
->green
.length
= 4;
162 var
->blue
.length
= 4;
164 var
->green
.offset
= 4;
165 var
->blue
.offset
= 0;
169 var
->green
.length
= 6;
170 var
->blue
.length
= 5;
171 var
->red
.offset
= 11;
172 var
->green
.offset
= 5;
173 var
->blue
.offset
= 0;
177 var
->green
.length
= 6;
178 var
->blue
.length
= 6;
179 var
->red
.offset
= 12;
180 var
->green
.offset
= 6;
181 var
->blue
.offset
= 0;
185 var
->green
.length
= 8;
186 var
->blue
.length
= 8;
187 var
->red
.offset
= 16;
188 var
->green
.offset
= 8;
189 var
->blue
.offset
= 0;
197 * Calculate lcd register values from var setting & save into hw
199 static void nuc900fb_calculate_lcd_regs(const struct fb_info
*info
,
200 struct nuc900fb_hw
*regs
)
202 const struct fb_var_screeninfo
*var
= &info
->var
;
203 int vtt
= var
->height
+ var
->upper_margin
+ var
->lower_margin
;
204 int htt
= var
->width
+ var
->left_margin
+ var
->right_margin
;
205 int hsync
= var
->width
+ var
->right_margin
;
206 int vsync
= var
->height
+ var
->lower_margin
;
208 regs
->lcd_crtc_size
= LCM_CRTC_SIZE_VTTVAL(vtt
) |
209 LCM_CRTC_SIZE_HTTVAL(htt
);
210 regs
->lcd_crtc_dend
= LCM_CRTC_DEND_VDENDVAL(var
->height
) |
211 LCM_CRTC_DEND_HDENDVAL(var
->width
);
212 regs
->lcd_crtc_hr
= LCM_CRTC_HR_EVAL(var
->width
+ 5) |
213 LCM_CRTC_HR_SVAL(var
->width
+ 1);
214 regs
->lcd_crtc_hsync
= LCM_CRTC_HSYNC_EVAL(hsync
+ var
->hsync_len
) |
215 LCM_CRTC_HSYNC_SVAL(hsync
);
216 regs
->lcd_crtc_vr
= LCM_CRTC_VR_EVAL(vsync
+ var
->vsync_len
) |
217 LCM_CRTC_VR_SVAL(vsync
);
222 * Activate (set) the controller from the given framebuffer
225 static void nuc900fb_activate_var(struct fb_info
*info
)
227 struct nuc900fb_info
*fbi
= info
->par
;
228 void __iomem
*regs
= fbi
->io
;
229 struct fb_var_screeninfo
*var
= &info
->var
;
232 clkdiv
= nuc900fb_calc_pixclk(fbi
, var
->pixclock
) - 1;
236 nuc900fb_calculate_lcd_regs(info
, &fbi
->regs
);
238 /* set the new lcd registers*/
240 dev_dbg(fbi
->dev
, "new lcd register set:\n");
241 dev_dbg(fbi
->dev
, "dccs = 0x%08x\n", fbi
->regs
.lcd_dccs
);
242 dev_dbg(fbi
->dev
, "dev_ctl = 0x%08x\n", fbi
->regs
.lcd_device_ctrl
);
243 dev_dbg(fbi
->dev
, "crtc_size = 0x%08x\n", fbi
->regs
.lcd_crtc_size
);
244 dev_dbg(fbi
->dev
, "crtc_dend = 0x%08x\n", fbi
->regs
.lcd_crtc_dend
);
245 dev_dbg(fbi
->dev
, "crtc_hr = 0x%08x\n", fbi
->regs
.lcd_crtc_hr
);
246 dev_dbg(fbi
->dev
, "crtc_hsync = 0x%08x\n", fbi
->regs
.lcd_crtc_hsync
);
247 dev_dbg(fbi
->dev
, "crtc_vr = 0x%08x\n", fbi
->regs
.lcd_crtc_vr
);
249 writel(fbi
->regs
.lcd_device_ctrl
, regs
+ REG_LCM_DEV_CTRL
);
250 writel(fbi
->regs
.lcd_crtc_size
, regs
+ REG_LCM_CRTC_SIZE
);
251 writel(fbi
->regs
.lcd_crtc_dend
, regs
+ REG_LCM_CRTC_DEND
);
252 writel(fbi
->regs
.lcd_crtc_hr
, regs
+ REG_LCM_CRTC_HR
);
253 writel(fbi
->regs
.lcd_crtc_hsync
, regs
+ REG_LCM_CRTC_HSYNC
);
254 writel(fbi
->regs
.lcd_crtc_vr
, regs
+ REG_LCM_CRTC_VR
);
256 /* set lcd address pointers */
257 nuc900fb_set_lcdaddr(info
);
259 writel(fbi
->regs
.lcd_dccs
, regs
+ REG_LCM_DCCS
);
263 * Alters the hardware state.
266 static int nuc900fb_set_par(struct fb_info
*info
)
268 struct fb_var_screeninfo
*var
= &info
->var
;
270 switch (var
->bits_per_pixel
) {
276 info
->fix
.visual
= FB_VISUAL_TRUECOLOR
;
279 info
->fix
.visual
= FB_VISUAL_MONO01
;
282 info
->fix
.visual
= FB_VISUAL_PSEUDOCOLOR
;
286 info
->fix
.line_length
= (var
->xres_virtual
* var
->bits_per_pixel
) / 8;
288 /* activate this new configuration */
289 nuc900fb_activate_var(info
);
293 static inline unsigned int chan_to_field(unsigned int chan
,
294 struct fb_bitfield
*bf
)
297 chan
>>= 16 - bf
->length
;
298 return chan
<< bf
->offset
;
301 static int nuc900fb_setcolreg(unsigned regno
,
302 unsigned red
, unsigned green
, unsigned blue
,
303 unsigned transp
, struct fb_info
*info
)
307 switch (info
->fix
.visual
) {
308 case FB_VISUAL_TRUECOLOR
:
309 /* true-colour, use pseuo-palette */
311 u32
*pal
= info
->pseudo_palette
;
313 val
= chan_to_field(red
, &info
->var
.red
);
314 val
|= chan_to_field(green
, &info
->var
.green
);
315 val
|= chan_to_field(blue
, &info
->var
.blue
);
321 return 1; /* unknown type */
330 static int nuc900fb_blank(int blank_mode
, struct fb_info
*info
)
336 static struct fb_ops nuc900fb_ops
= {
337 .owner
= THIS_MODULE
,
338 .fb_check_var
= nuc900fb_check_var
,
339 .fb_set_par
= nuc900fb_set_par
,
340 .fb_blank
= nuc900fb_blank
,
341 .fb_setcolreg
= nuc900fb_setcolreg
,
342 .fb_fillrect
= cfb_fillrect
,
343 .fb_copyarea
= cfb_copyarea
,
344 .fb_imageblit
= cfb_imageblit
,
348 static inline void modify_gpio(void __iomem
*reg
,
349 unsigned long set
, unsigned long mask
)
352 tmp
= readl(reg
) & ~mask
;
353 writel(tmp
| set
, reg
);
357 * Initialise LCD-related registers
359 static int nuc900fb_init_registers(struct fb_info
*info
)
361 struct nuc900fb_info
*fbi
= info
->par
;
362 struct nuc900fb_mach_info
*mach_info
= fbi
->dev
->platform_data
;
363 void __iomem
*regs
= fbi
->io
;
365 /*reset the display engine*/
366 writel(0, regs
+ REG_LCM_DCCS
);
367 writel(readl(regs
+ REG_LCM_DCCS
) | LCM_DCCS_ENG_RST
,
368 regs
+ REG_LCM_DCCS
);
370 writel(readl(regs
+ REG_LCM_DCCS
) & (~LCM_DCCS_ENG_RST
),
371 regs
+ REG_LCM_DCCS
);
374 writel(0, regs
+ REG_LCM_DEV_CTRL
);
376 /* config gpio output */
377 modify_gpio(W90X900_VA_GPIO
+ 0x54, mach_info
->gpio_dir
,
378 mach_info
->gpio_dir_mask
);
379 modify_gpio(W90X900_VA_GPIO
+ 0x58, mach_info
->gpio_data
,
380 mach_info
->gpio_data_mask
);
387 * Alloc the SDRAM region of NUC900 for the frame buffer.
388 * The buffer should be a non-cached, non-buffered, memory region
389 * to allow palette and pixel writes without flushing the cache.
391 static int __init
nuc900fb_map_video_memory(struct fb_info
*info
)
393 struct nuc900fb_info
*fbi
= info
->par
;
395 unsigned long map_size
= PAGE_ALIGN(info
->fix
.smem_len
);
397 dev_dbg(fbi
->dev
, "nuc900fb_map_video_memory(fbi=%p) map_size %lu\n",
400 info
->screen_base
= dma_alloc_writecombine(fbi
->dev
, map_size
,
401 &map_dma
, GFP_KERNEL
);
403 if (!info
->screen_base
)
406 memset(info
->screen_base
, 0x00, map_size
);
407 info
->fix
.smem_start
= map_dma
;
412 static inline void nuc900fb_unmap_video_memory(struct fb_info
*info
)
414 struct nuc900fb_info
*fbi
= info
->par
;
415 dma_free_writecombine(fbi
->dev
, PAGE_ALIGN(info
->fix
.smem_len
),
416 info
->screen_base
, info
->fix
.smem_start
);
419 static irqreturn_t
nuc900fb_irqhandler(int irq
, void *dev_id
)
421 struct nuc900fb_info
*fbi
= dev_id
;
422 void __iomem
*regs
= fbi
->io
;
423 void __iomem
*irq_base
= fbi
->irq_base
;
424 unsigned long lcdirq
= readl(regs
+ REG_LCM_INT_CS
);
426 if (lcdirq
& LCM_INT_CS_DISP_F_STATUS
) {
427 writel(readl(irq_base
) | 1<<30, irq_base
);
430 if ((readl(regs
+ REG_LCM_DCCS
) &
431 LCM_DCCS_SINGLE
) == LCM_DCCS_SINGLE
)
432 while ((readl(regs
+ REG_LCM_DCCS
) &
433 LCM_DCCS_VA_EN
) == LCM_DCCS_VA_EN
)
435 /* display_out-enable */
436 writel(readl(regs
+ REG_LCM_DCCS
) | LCM_DCCS_DISP_OUT_EN
,
437 regs
+ REG_LCM_DCCS
);
439 writel(readl(regs
+ REG_LCM_DCCS
) | LCM_DCCS_VA_EN
,
440 regs
+ REG_LCM_DCCS
);
441 } else if (lcdirq
& LCM_INT_CS_UNDERRUN_INT
) {
442 writel(readl(irq_base
) | LCM_INT_CS_UNDERRUN_INT
, irq_base
);
443 } else if (lcdirq
& LCM_INT_CS_BUS_ERROR_INT
) {
444 writel(readl(irq_base
) | LCM_INT_CS_BUS_ERROR_INT
, irq_base
);
450 #ifdef CONFIG_CPU_FREQ
452 static int nuc900fb_cpufreq_transition(struct notifier_block
*nb
,
453 unsigned long val
, void *data
)
455 struct nuc900fb_info
*info
;
456 struct fb_info
*fbinfo
;
458 info
= container_of(nb
, struct nuc900fb_info
, freq_transition
);
459 fbinfo
= platform_get_drvdata(to_platform_device(info
->dev
));
461 delta_f
= info
->clk_rate
- clk_get_rate(info
->clk
);
463 if ((val
== CPUFREQ_POSTCHANGE
&& delta_f
> 0) ||
464 (val
== CPUFREQ_PRECHANGE
&& delta_f
< 0)) {
465 info
->clk_rate
= clk_get_rate(info
->clk
);
466 nuc900fb_activate_var(fbinfo
);
472 static inline int nuc900fb_cpufreq_register(struct nuc900fb_info
*fbi
)
474 fbi
->freq_transition
.notifier_call
= nuc900fb_cpufreq_transition
;
475 return cpufreq_register_notifier(&fbi
->freq_transition
,
476 CPUFREQ_TRANSITION_NOTIFIER
);
479 static inline void nuc900fb_cpufreq_deregister(struct nuc900fb_info
*fbi
)
481 cpufreq_unregister_notifier(&fbi
->freq_transition
,
482 CPUFREQ_TRANSITION_NOTIFIER
);
485 static inline int nuc900fb_cpufreq_transition(struct notifier_block
*nb
,
486 unsigned long val
, void *data
)
491 static inline int nuc900fb_cpufreq_register(struct nuc900fb_info
*fbi
)
496 static inline void nuc900fb_cpufreq_deregister(struct nuc900fb_info
*info
)
501 static char driver_name
[] = "nuc900fb";
503 static int __devinit
nuc900fb_probe(struct platform_device
*pdev
)
505 struct nuc900fb_info
*fbi
;
506 struct nuc900fb_display
*display
;
507 struct fb_info
*fbinfo
;
508 struct nuc900fb_mach_info
*mach_info
;
509 struct resource
*res
;
515 dev_dbg(&pdev
->dev
, "devinit\n");
516 mach_info
= pdev
->dev
.platform_data
;
517 if (mach_info
== NULL
) {
519 "no platform data for lcd, cannot attach\n");
523 if (mach_info
->default_display
> mach_info
->num_displays
) {
525 "default display No. is %d but only %d displays \n",
526 mach_info
->default_display
, mach_info
->num_displays
);
531 display
= mach_info
->displays
+ mach_info
->default_display
;
533 irq
= platform_get_irq(pdev
, 0);
535 dev_err(&pdev
->dev
, "no irq for device\n");
539 fbinfo
= framebuffer_alloc(sizeof(struct nuc900fb_info
), &pdev
->dev
);
543 platform_set_drvdata(pdev
, fbinfo
);
546 fbi
->dev
= &pdev
->dev
;
548 #ifdef CONFIG_CPU_NUC950
549 fbi
->drv_type
= LCDDRV_NUC950
;
552 res
= platform_get_resource(pdev
, IORESOURCE_MEM
, 0);
554 size
= (res
->end
- res
->start
) + 1;
555 fbi
->mem
= request_mem_region(res
->start
, size
, pdev
->name
);
556 if (fbi
->mem
== NULL
) {
557 dev_err(&pdev
->dev
, "failed to alloc memory region\n");
562 fbi
->io
= ioremap(res
->start
, size
);
563 if (fbi
->io
== NULL
) {
564 dev_err(&pdev
->dev
, "ioremap() of lcd registers failed\n");
566 goto release_mem_region
;
569 fbi
->irq_base
= fbi
->io
+ REG_LCM_INT_CS
;
573 writel(0, fbi
->io
+ REG_LCM_DCCS
);
576 strcpy(fbinfo
->fix
.id
, driver_name
);
577 fbinfo
->fix
.type
= FB_TYPE_PACKED_PIXELS
;
578 fbinfo
->fix
.type_aux
= 0;
579 fbinfo
->fix
.xpanstep
= 0;
580 fbinfo
->fix
.ypanstep
= 0;
581 fbinfo
->fix
.ywrapstep
= 0;
582 fbinfo
->fix
.accel
= FB_ACCEL_NONE
;
583 fbinfo
->var
.nonstd
= 0;
584 fbinfo
->var
.activate
= FB_ACTIVATE_NOW
;
585 fbinfo
->var
.accel_flags
= 0;
586 fbinfo
->var
.vmode
= FB_VMODE_NONINTERLACED
;
587 fbinfo
->fbops
= &nuc900fb_ops
;
588 fbinfo
->flags
= FBINFO_FLAG_DEFAULT
;
589 fbinfo
->pseudo_palette
= &fbi
->pseudo_pal
;
591 ret
= request_irq(irq
, nuc900fb_irqhandler
, IRQF_DISABLED
,
594 dev_err(&pdev
->dev
, "cannot register irq handler %d -err %d\n",
600 fbi
->clk
= clk_get(&pdev
->dev
, NULL
);
601 if (IS_ERR(fbi
->clk
)) {
602 printk(KERN_ERR
"nuc900-lcd:failed to get lcd clock source\n");
603 ret
= PTR_ERR(fbi
->clk
);
607 clk_enable(fbi
->clk
);
608 dev_dbg(&pdev
->dev
, "got and enabled clock\n");
610 fbi
->clk_rate
= clk_get_rate(fbi
->clk
);
612 /* calutate the video buffer size */
613 for (i
= 0; i
< mach_info
->num_displays
; i
++) {
614 unsigned long smem_len
= mach_info
->displays
[i
].xres
;
615 smem_len
*= mach_info
->displays
[i
].yres
;
616 smem_len
*= mach_info
->displays
[i
].bpp
;
618 if (fbinfo
->fix
.smem_len
< smem_len
)
619 fbinfo
->fix
.smem_len
= smem_len
;
622 /* Initialize Video Memory */
623 ret
= nuc900fb_map_video_memory(fbinfo
);
625 printk(KERN_ERR
"Failed to allocate video RAM: %x\n", ret
);
629 dev_dbg(&pdev
->dev
, "got video memory\n");
631 fbinfo
->var
.xres
= display
->xres
;
632 fbinfo
->var
.yres
= display
->yres
;
633 fbinfo
->var
.bits_per_pixel
= display
->bpp
;
635 nuc900fb_init_registers(fbinfo
);
637 nuc900fb_check_var(&fbinfo
->var
, fbinfo
);
639 ret
= nuc900fb_cpufreq_register(fbi
);
641 dev_err(&pdev
->dev
, "Failed to register cpufreq\n");
642 goto free_video_memory
;
645 ret
= register_framebuffer(fbinfo
);
647 printk(KERN_ERR
"failed to register framebuffer device: %d\n",
652 printk(KERN_INFO
"fb%d: %s frame buffer device\n",
653 fbinfo
->node
, fbinfo
->fix
.id
);
658 nuc900fb_cpufreq_deregister(fbi
);
660 nuc900fb_unmap_video_memory(fbinfo
);
662 clk_disable(fbi
->clk
);
669 release_mem_region(res
->start
, size
);
671 framebuffer_release(fbinfo
);
676 * shutdown the lcd controller
678 static void nuc900fb_stop_lcd(struct fb_info
*info
)
680 struct nuc900fb_info
*fbi
= info
->par
;
681 void __iomem
*regs
= fbi
->io
;
683 writel((~LCM_DCCS_DISP_INT_EN
) | (~LCM_DCCS_VA_EN
) | (~LCM_DCCS_OSD_EN
),
684 regs
+ REG_LCM_DCCS
);
690 static int nuc900fb_remove(struct platform_device
*pdev
)
692 struct fb_info
*fbinfo
= platform_get_drvdata(pdev
);
693 struct nuc900fb_info
*fbi
= fbinfo
->par
;
696 nuc900fb_stop_lcd(fbinfo
);
699 unregister_framebuffer(fbinfo
);
700 nuc900fb_cpufreq_deregister(fbi
);
701 nuc900fb_unmap_video_memory(fbinfo
);
705 irq
= platform_get_irq(pdev
, 0);
708 release_resource(fbi
->mem
);
711 platform_set_drvdata(pdev
, NULL
);
712 framebuffer_release(fbinfo
);
720 * suspend and resume support for the lcd controller
723 static int nuc900fb_suspend(struct platform_device
*dev
, pm_message_t state
)
725 struct fb_info
*fbinfo
= platform_get_drvdata(dev
);
726 struct nuc900fb_info
*info
= fbinfo
->par
;
728 nuc900fb_stop_lcd(fbinfo
);
730 clk_disable(info
->clk
);
734 static int nuc900fb_resume(struct platform_device
*dev
)
736 struct fb_info
*fbinfo
= platform_get_drvdata(dev
);
737 struct nuc900fb_info
*fbi
= fbinfo
->par
;
739 printk(KERN_INFO
"nuc900fb resume\n");
741 clk_enable(fbi
->clk
);
744 nuc900fb_init_registers(fbinfo
);
745 nuc900fb_activate_var(fbinfo
);
751 #define nuc900fb_suspend NULL
752 #define nuc900fb_resume NULL
755 static struct platform_driver nuc900fb_driver
= {
756 .probe
= nuc900fb_probe
,
757 .remove
= nuc900fb_remove
,
758 .suspend
= nuc900fb_suspend
,
759 .resume
= nuc900fb_resume
,
761 .name
= "nuc900-lcd",
762 .owner
= THIS_MODULE
,
766 int __devinit
nuc900fb_init(void)
768 return platform_driver_register(&nuc900fb_driver
);
771 static void __exit
nuc900fb_cleanup(void)
773 platform_driver_unregister(&nuc900fb_driver
);
776 module_init(nuc900fb_init
);
777 module_exit(nuc900fb_cleanup
);
779 MODULE_DESCRIPTION("Framebuffer driver for the NUC900");
780 MODULE_LICENSE("GPL");