diff options
Diffstat (limited to 'drivers/video/atmel_lcdfb.c')
-rw-r--r-- | drivers/video/atmel_lcdfb.c | 165 |
1 files changed, 138 insertions, 27 deletions
diff --git a/drivers/video/atmel_lcdfb.c b/drivers/video/atmel_lcdfb.c index b004036d4087..75dac578104f 100644 --- a/drivers/video/atmel_lcdfb.c +++ b/drivers/video/atmel_lcdfb.c | |||
@@ -18,9 +18,9 @@ | |||
18 | #include <linux/delay.h> | 18 | #include <linux/delay.h> |
19 | #include <linux/backlight.h> | 19 | #include <linux/backlight.h> |
20 | 20 | ||
21 | #include <asm/arch/board.h> | 21 | #include <mach/board.h> |
22 | #include <asm/arch/cpu.h> | 22 | #include <mach/cpu.h> |
23 | #include <asm/arch/gpio.h> | 23 | #include <mach/gpio.h> |
24 | 24 | ||
25 | #include <video/atmel_lcdc.h> | 25 | #include <video/atmel_lcdc.h> |
26 | 26 | ||
@@ -39,7 +39,9 @@ | |||
39 | #endif | 39 | #endif |
40 | 40 | ||
41 | #if defined(CONFIG_ARCH_AT91) | 41 | #if defined(CONFIG_ARCH_AT91) |
42 | #define ATMEL_LCDFB_FBINFO_DEFAULT FBINFO_DEFAULT | 42 | #define ATMEL_LCDFB_FBINFO_DEFAULT (FBINFO_DEFAULT \ |
43 | | FBINFO_PARTIAL_PAN_OK \ | ||
44 | | FBINFO_HWACCEL_YPAN) | ||
43 | 45 | ||
44 | static inline void atmel_lcdfb_update_dma2d(struct atmel_lcdfb_info *sinfo, | 46 | static inline void atmel_lcdfb_update_dma2d(struct atmel_lcdfb_info *sinfo, |
45 | struct fb_var_screeninfo *var) | 47 | struct fb_var_screeninfo *var) |
@@ -177,7 +179,7 @@ static struct fb_fix_screeninfo atmel_lcdfb_fix __initdata = { | |||
177 | .type = FB_TYPE_PACKED_PIXELS, | 179 | .type = FB_TYPE_PACKED_PIXELS, |
178 | .visual = FB_VISUAL_TRUECOLOR, | 180 | .visual = FB_VISUAL_TRUECOLOR, |
179 | .xpanstep = 0, | 181 | .xpanstep = 0, |
180 | .ypanstep = 0, | 182 | .ypanstep = 1, |
181 | .ywrapstep = 0, | 183 | .ywrapstep = 0, |
182 | .accel = FB_ACCEL_NONE, | 184 | .accel = FB_ACCEL_NONE, |
183 | }; | 185 | }; |
@@ -206,6 +208,36 @@ static unsigned long compute_hozval(unsigned long xres, unsigned long lcdcon2) | |||
206 | return value; | 208 | return value; |
207 | } | 209 | } |
208 | 210 | ||
211 | static void atmel_lcdfb_stop_nowait(struct atmel_lcdfb_info *sinfo) | ||
212 | { | ||
213 | /* Turn off the LCD controller and the DMA controller */ | ||
214 | lcdc_writel(sinfo, ATMEL_LCDC_PWRCON, | ||
215 | sinfo->guard_time << ATMEL_LCDC_GUARDT_OFFSET); | ||
216 | |||
217 | /* Wait for the LCDC core to become idle */ | ||
218 | while (lcdc_readl(sinfo, ATMEL_LCDC_PWRCON) & ATMEL_LCDC_BUSY) | ||
219 | msleep(10); | ||
220 | |||
221 | lcdc_writel(sinfo, ATMEL_LCDC_DMACON, 0); | ||
222 | } | ||
223 | |||
224 | static void atmel_lcdfb_stop(struct atmel_lcdfb_info *sinfo) | ||
225 | { | ||
226 | atmel_lcdfb_stop_nowait(sinfo); | ||
227 | |||
228 | /* Wait for DMA engine to become idle... */ | ||
229 | while (lcdc_readl(sinfo, ATMEL_LCDC_DMACON) & ATMEL_LCDC_DMABUSY) | ||
230 | msleep(10); | ||
231 | } | ||
232 | |||
233 | static void atmel_lcdfb_start(struct atmel_lcdfb_info *sinfo) | ||
234 | { | ||
235 | lcdc_writel(sinfo, ATMEL_LCDC_DMACON, sinfo->default_dmacon); | ||
236 | lcdc_writel(sinfo, ATMEL_LCDC_PWRCON, | ||
237 | (sinfo->guard_time << ATMEL_LCDC_GUARDT_OFFSET) | ||
238 | | ATMEL_LCDC_PWR); | ||
239 | } | ||
240 | |||
209 | static void atmel_lcdfb_update_dma(struct fb_info *info, | 241 | static void atmel_lcdfb_update_dma(struct fb_info *info, |
210 | struct fb_var_screeninfo *var) | 242 | struct fb_var_screeninfo *var) |
211 | { | 243 | { |
@@ -240,9 +272,11 @@ static int atmel_lcdfb_alloc_video_memory(struct atmel_lcdfb_info *sinfo) | |||
240 | { | 272 | { |
241 | struct fb_info *info = sinfo->info; | 273 | struct fb_info *info = sinfo->info; |
242 | struct fb_var_screeninfo *var = &info->var; | 274 | struct fb_var_screeninfo *var = &info->var; |
275 | unsigned int smem_len; | ||
243 | 276 | ||
244 | info->fix.smem_len = (var->xres_virtual * var->yres_virtual | 277 | smem_len = (var->xres_virtual * var->yres_virtual |
245 | * ((var->bits_per_pixel + 7) / 8)); | 278 | * ((var->bits_per_pixel + 7) / 8)); |
279 | info->fix.smem_len = max(smem_len, sinfo->smem_len); | ||
246 | 280 | ||
247 | info->screen_base = dma_alloc_writecombine(info->device, info->fix.smem_len, | 281 | info->screen_base = dma_alloc_writecombine(info->device, info->fix.smem_len, |
248 | (dma_addr_t *)&info->fix.smem_start, GFP_KERNEL); | 282 | (dma_addr_t *)&info->fix.smem_start, GFP_KERNEL); |
@@ -256,6 +290,20 @@ static int atmel_lcdfb_alloc_video_memory(struct atmel_lcdfb_info *sinfo) | |||
256 | return 0; | 290 | return 0; |
257 | } | 291 | } |
258 | 292 | ||
293 | static const struct fb_videomode *atmel_lcdfb_choose_mode(struct fb_var_screeninfo *var, | ||
294 | struct fb_info *info) | ||
295 | { | ||
296 | struct fb_videomode varfbmode; | ||
297 | const struct fb_videomode *fbmode = NULL; | ||
298 | |||
299 | fb_var_to_videomode(&varfbmode, var); | ||
300 | fbmode = fb_find_nearest_mode(&varfbmode, &info->modelist); | ||
301 | if (fbmode) | ||
302 | fb_videomode_to_var(var, fbmode); | ||
303 | return fbmode; | ||
304 | } | ||
305 | |||
306 | |||
259 | /** | 307 | /** |
260 | * atmel_lcdfb_check_var - Validates a var passed in. | 308 | * atmel_lcdfb_check_var - Validates a var passed in. |
261 | * @var: frame buffer variable screen structure | 309 | * @var: frame buffer variable screen structure |
@@ -289,6 +337,15 @@ static int atmel_lcdfb_check_var(struct fb_var_screeninfo *var, | |||
289 | clk_value_khz = clk_get_rate(sinfo->lcdc_clk) / 1000; | 337 | clk_value_khz = clk_get_rate(sinfo->lcdc_clk) / 1000; |
290 | 338 | ||
291 | dev_dbg(dev, "%s:\n", __func__); | 339 | dev_dbg(dev, "%s:\n", __func__); |
340 | |||
341 | if (!(var->pixclock && var->bits_per_pixel)) { | ||
342 | /* choose a suitable mode if possible */ | ||
343 | if (!atmel_lcdfb_choose_mode(var, info)) { | ||
344 | dev_err(dev, "needed value not specified\n"); | ||
345 | return -EINVAL; | ||
346 | } | ||
347 | } | ||
348 | |||
292 | dev_dbg(dev, " resolution: %ux%u\n", var->xres, var->yres); | 349 | dev_dbg(dev, " resolution: %ux%u\n", var->xres, var->yres); |
293 | dev_dbg(dev, " pixclk: %lu KHz\n", PICOS2KHZ(var->pixclock)); | 350 | dev_dbg(dev, " pixclk: %lu KHz\n", PICOS2KHZ(var->pixclock)); |
294 | dev_dbg(dev, " bpp: %u\n", var->bits_per_pixel); | 351 | dev_dbg(dev, " bpp: %u\n", var->bits_per_pixel); |
@@ -299,6 +356,13 @@ static int atmel_lcdfb_check_var(struct fb_var_screeninfo *var, | |||
299 | return -EINVAL; | 356 | return -EINVAL; |
300 | } | 357 | } |
301 | 358 | ||
359 | /* Do not allow to have real resoulution larger than virtual */ | ||
360 | if (var->xres > var->xres_virtual) | ||
361 | var->xres_virtual = var->xres; | ||
362 | |||
363 | if (var->yres > var->yres_virtual) | ||
364 | var->yres_virtual = var->yres; | ||
365 | |||
302 | /* Force same alignment for each line */ | 366 | /* Force same alignment for each line */ |
303 | var->xres = (var->xres + 3) & ~3UL; | 367 | var->xres = (var->xres + 3) & ~3UL; |
304 | var->xres_virtual = (var->xres_virtual + 3) & ~3UL; | 368 | var->xres_virtual = (var->xres_virtual + 3) & ~3UL; |
@@ -379,6 +443,17 @@ static int atmel_lcdfb_check_var(struct fb_var_screeninfo *var, | |||
379 | return 0; | 443 | return 0; |
380 | } | 444 | } |
381 | 445 | ||
446 | /* | ||
447 | * LCD reset sequence | ||
448 | */ | ||
449 | static void atmel_lcdfb_reset(struct atmel_lcdfb_info *sinfo) | ||
450 | { | ||
451 | might_sleep(); | ||
452 | |||
453 | atmel_lcdfb_stop(sinfo); | ||
454 | atmel_lcdfb_start(sinfo); | ||
455 | } | ||
456 | |||
382 | /** | 457 | /** |
383 | * atmel_lcdfb_set_par - Alters the hardware state. | 458 | * atmel_lcdfb_set_par - Alters the hardware state. |
384 | * @info: frame buffer structure that represents a single frame buffer | 459 | * @info: frame buffer structure that represents a single frame buffer |
@@ -401,19 +476,14 @@ static int atmel_lcdfb_set_par(struct fb_info *info) | |||
401 | unsigned long clk_value_khz; | 476 | unsigned long clk_value_khz; |
402 | unsigned long bits_per_line; | 477 | unsigned long bits_per_line; |
403 | 478 | ||
479 | might_sleep(); | ||
480 | |||
404 | dev_dbg(info->device, "%s:\n", __func__); | 481 | dev_dbg(info->device, "%s:\n", __func__); |
405 | dev_dbg(info->device, " * resolution: %ux%u (%ux%u virtual)\n", | 482 | dev_dbg(info->device, " * resolution: %ux%u (%ux%u virtual)\n", |
406 | info->var.xres, info->var.yres, | 483 | info->var.xres, info->var.yres, |
407 | info->var.xres_virtual, info->var.yres_virtual); | 484 | info->var.xres_virtual, info->var.yres_virtual); |
408 | 485 | ||
409 | /* Turn off the LCD controller and the DMA controller */ | 486 | atmel_lcdfb_stop_nowait(sinfo); |
410 | lcdc_writel(sinfo, ATMEL_LCDC_PWRCON, sinfo->guard_time << ATMEL_LCDC_GUARDT_OFFSET); | ||
411 | |||
412 | /* Wait for the LCDC core to become idle */ | ||
413 | while (lcdc_readl(sinfo, ATMEL_LCDC_PWRCON) & ATMEL_LCDC_BUSY) | ||
414 | msleep(10); | ||
415 | |||
416 | lcdc_writel(sinfo, ATMEL_LCDC_DMACON, 0); | ||
417 | 487 | ||
418 | if (info->var.bits_per_pixel == 1) | 488 | if (info->var.bits_per_pixel == 1) |
419 | info->fix.visual = FB_VISUAL_MONO01; | 489 | info->fix.visual = FB_VISUAL_MONO01; |
@@ -511,18 +581,14 @@ static int atmel_lcdfb_set_par(struct fb_info *info) | |||
511 | 581 | ||
512 | /* Disable all interrupts */ | 582 | /* Disable all interrupts */ |
513 | lcdc_writel(sinfo, ATMEL_LCDC_IDR, ~0UL); | 583 | lcdc_writel(sinfo, ATMEL_LCDC_IDR, ~0UL); |
584 | /* Enable FIFO & DMA errors */ | ||
585 | lcdc_writel(sinfo, ATMEL_LCDC_IER, ATMEL_LCDC_UFLWI | ATMEL_LCDC_OWRI | ATMEL_LCDC_MERI); | ||
514 | 586 | ||
515 | /* ...wait for DMA engine to become idle... */ | 587 | /* ...wait for DMA engine to become idle... */ |
516 | while (lcdc_readl(sinfo, ATMEL_LCDC_DMACON) & ATMEL_LCDC_DMABUSY) | 588 | while (lcdc_readl(sinfo, ATMEL_LCDC_DMACON) & ATMEL_LCDC_DMABUSY) |
517 | msleep(10); | 589 | msleep(10); |
518 | 590 | ||
519 | dev_dbg(info->device, " * re-enable DMA engine\n"); | 591 | atmel_lcdfb_start(sinfo); |
520 | /* ...and enable it with updated configuration */ | ||
521 | lcdc_writel(sinfo, ATMEL_LCDC_DMACON, sinfo->default_dmacon); | ||
522 | |||
523 | dev_dbg(info->device, " * re-enable LCDC core\n"); | ||
524 | lcdc_writel(sinfo, ATMEL_LCDC_PWRCON, | ||
525 | (sinfo->guard_time << ATMEL_LCDC_GUARDT_OFFSET) | ATMEL_LCDC_PWR); | ||
526 | 592 | ||
527 | dev_dbg(info->device, " * DONE\n"); | 593 | dev_dbg(info->device, " * DONE\n"); |
528 | 594 | ||
@@ -645,10 +711,26 @@ static irqreturn_t atmel_lcdfb_interrupt(int irq, void *dev_id) | |||
645 | u32 status; | 711 | u32 status; |
646 | 712 | ||
647 | status = lcdc_readl(sinfo, ATMEL_LCDC_ISR); | 713 | status = lcdc_readl(sinfo, ATMEL_LCDC_ISR); |
648 | lcdc_writel(sinfo, ATMEL_LCDC_IDR, status); | 714 | if (status & ATMEL_LCDC_UFLWI) { |
715 | dev_warn(info->device, "FIFO underflow %#x\n", status); | ||
716 | /* reset DMA and FIFO to avoid screen shifting */ | ||
717 | schedule_work(&sinfo->task); | ||
718 | } | ||
719 | lcdc_writel(sinfo, ATMEL_LCDC_ICR, status); | ||
649 | return IRQ_HANDLED; | 720 | return IRQ_HANDLED; |
650 | } | 721 | } |
651 | 722 | ||
723 | /* | ||
724 | * LCD controller task (to reset the LCD) | ||
725 | */ | ||
726 | static void atmel_lcdfb_task(struct work_struct *work) | ||
727 | { | ||
728 | struct atmel_lcdfb_info *sinfo = | ||
729 | container_of(work, struct atmel_lcdfb_info, task); | ||
730 | |||
731 | atmel_lcdfb_reset(sinfo); | ||
732 | } | ||
733 | |||
652 | static int __init atmel_lcdfb_init_fbinfo(struct atmel_lcdfb_info *sinfo) | 734 | static int __init atmel_lcdfb_init_fbinfo(struct atmel_lcdfb_info *sinfo) |
653 | { | 735 | { |
654 | struct fb_info *info = sinfo->info; | 736 | struct fb_info *info = sinfo->info; |
@@ -691,6 +773,7 @@ static int __init atmel_lcdfb_probe(struct platform_device *pdev) | |||
691 | struct fb_info *info; | 773 | struct fb_info *info; |
692 | struct atmel_lcdfb_info *sinfo; | 774 | struct atmel_lcdfb_info *sinfo; |
693 | struct atmel_lcdfb_info *pdata_sinfo; | 775 | struct atmel_lcdfb_info *pdata_sinfo; |
776 | struct fb_videomode fbmode; | ||
694 | struct resource *regs = NULL; | 777 | struct resource *regs = NULL; |
695 | struct resource *map = NULL; | 778 | struct resource *map = NULL; |
696 | int ret; | 779 | int ret; |
@@ -714,6 +797,7 @@ static int __init atmel_lcdfb_probe(struct platform_device *pdev) | |||
714 | sinfo->default_monspecs = pdata_sinfo->default_monspecs; | 797 | sinfo->default_monspecs = pdata_sinfo->default_monspecs; |
715 | sinfo->atmel_lcdfb_power_control = pdata_sinfo->atmel_lcdfb_power_control; | 798 | sinfo->atmel_lcdfb_power_control = pdata_sinfo->atmel_lcdfb_power_control; |
716 | sinfo->guard_time = pdata_sinfo->guard_time; | 799 | sinfo->guard_time = pdata_sinfo->guard_time; |
800 | sinfo->smem_len = pdata_sinfo->smem_len; | ||
717 | sinfo->lcdcon_is_backlight = pdata_sinfo->lcdcon_is_backlight; | 801 | sinfo->lcdcon_is_backlight = pdata_sinfo->lcdcon_is_backlight; |
718 | sinfo->lcd_wiring_mode = pdata_sinfo->lcd_wiring_mode; | 802 | sinfo->lcd_wiring_mode = pdata_sinfo->lcd_wiring_mode; |
719 | } else { | 803 | } else { |
@@ -824,6 +908,10 @@ static int __init atmel_lcdfb_probe(struct platform_device *pdev) | |||
824 | goto unmap_mmio; | 908 | goto unmap_mmio; |
825 | } | 909 | } |
826 | 910 | ||
911 | /* Some operations on the LCDC might sleep and | ||
912 | * require a preemptible task context */ | ||
913 | INIT_WORK(&sinfo->task, atmel_lcdfb_task); | ||
914 | |||
827 | ret = atmel_lcdfb_init_fbinfo(sinfo); | 915 | ret = atmel_lcdfb_init_fbinfo(sinfo); |
828 | if (ret < 0) { | 916 | if (ret < 0) { |
829 | dev_err(dev, "init fbinfo failed: %d\n", ret); | 917 | dev_err(dev, "init fbinfo failed: %d\n", ret); |
@@ -850,9 +938,13 @@ static int __init atmel_lcdfb_probe(struct platform_device *pdev) | |||
850 | ret = register_framebuffer(info); | 938 | ret = register_framebuffer(info); |
851 | if (ret < 0) { | 939 | if (ret < 0) { |
852 | dev_err(dev, "failed to register framebuffer device: %d\n", ret); | 940 | dev_err(dev, "failed to register framebuffer device: %d\n", ret); |
853 | goto free_cmap; | 941 | goto reset_drvdata; |
854 | } | 942 | } |
855 | 943 | ||
944 | /* add selected videomode to modelist */ | ||
945 | fb_var_to_videomode(&fbmode, &info->var); | ||
946 | fb_add_videomode(&fbmode, &info->modelist); | ||
947 | |||
856 | /* Power up the LCDC screen */ | 948 | /* Power up the LCDC screen */ |
857 | if (sinfo->atmel_lcdfb_power_control) | 949 | if (sinfo->atmel_lcdfb_power_control) |
858 | sinfo->atmel_lcdfb_power_control(1); | 950 | sinfo->atmel_lcdfb_power_control(1); |
@@ -862,10 +954,12 @@ static int __init atmel_lcdfb_probe(struct platform_device *pdev) | |||
862 | 954 | ||
863 | return 0; | 955 | return 0; |
864 | 956 | ||
865 | 957 | reset_drvdata: | |
958 | dev_set_drvdata(dev, NULL); | ||
866 | free_cmap: | 959 | free_cmap: |
867 | fb_dealloc_cmap(&info->cmap); | 960 | fb_dealloc_cmap(&info->cmap); |
868 | unregister_irqs: | 961 | unregister_irqs: |
962 | cancel_work_sync(&sinfo->task); | ||
869 | free_irq(sinfo->irq_base, info); | 963 | free_irq(sinfo->irq_base, info); |
870 | unmap_mmio: | 964 | unmap_mmio: |
871 | exit_backlight(sinfo); | 965 | exit_backlight(sinfo); |
@@ -898,11 +992,13 @@ static int __exit atmel_lcdfb_remove(struct platform_device *pdev) | |||
898 | { | 992 | { |
899 | struct device *dev = &pdev->dev; | 993 | struct device *dev = &pdev->dev; |
900 | struct fb_info *info = dev_get_drvdata(dev); | 994 | struct fb_info *info = dev_get_drvdata(dev); |
901 | struct atmel_lcdfb_info *sinfo = info->par; | 995 | struct atmel_lcdfb_info *sinfo; |
902 | 996 | ||
903 | if (!sinfo) | 997 | if (!info || !info->par) |
904 | return 0; | 998 | return 0; |
999 | sinfo = info->par; | ||
905 | 1000 | ||
1001 | cancel_work_sync(&sinfo->task); | ||
906 | exit_backlight(sinfo); | 1002 | exit_backlight(sinfo); |
907 | if (sinfo->atmel_lcdfb_power_control) | 1003 | if (sinfo->atmel_lcdfb_power_control) |
908 | sinfo->atmel_lcdfb_power_control(0); | 1004 | sinfo->atmel_lcdfb_power_control(0); |
@@ -935,11 +1031,20 @@ static int atmel_lcdfb_suspend(struct platform_device *pdev, pm_message_t mesg) | |||
935 | struct fb_info *info = platform_get_drvdata(pdev); | 1031 | struct fb_info *info = platform_get_drvdata(pdev); |
936 | struct atmel_lcdfb_info *sinfo = info->par; | 1032 | struct atmel_lcdfb_info *sinfo = info->par; |
937 | 1033 | ||
1034 | /* | ||
1035 | * We don't want to handle interrupts while the clock is | ||
1036 | * stopped. It may take forever. | ||
1037 | */ | ||
1038 | lcdc_writel(sinfo, ATMEL_LCDC_IDR, ~0UL); | ||
1039 | |||
938 | sinfo->saved_lcdcon = lcdc_readl(sinfo, ATMEL_LCDC_CONTRAST_VAL); | 1040 | sinfo->saved_lcdcon = lcdc_readl(sinfo, ATMEL_LCDC_CONTRAST_VAL); |
939 | lcdc_writel(sinfo, ATMEL_LCDC_CONTRAST_CTR, 0); | 1041 | lcdc_writel(sinfo, ATMEL_LCDC_CONTRAST_CTR, 0); |
940 | if (sinfo->atmel_lcdfb_power_control) | 1042 | if (sinfo->atmel_lcdfb_power_control) |
941 | sinfo->atmel_lcdfb_power_control(0); | 1043 | sinfo->atmel_lcdfb_power_control(0); |
1044 | |||
1045 | atmel_lcdfb_stop(sinfo); | ||
942 | atmel_lcdfb_stop_clock(sinfo); | 1046 | atmel_lcdfb_stop_clock(sinfo); |
1047 | |||
943 | return 0; | 1048 | return 0; |
944 | } | 1049 | } |
945 | 1050 | ||
@@ -949,9 +1054,15 @@ static int atmel_lcdfb_resume(struct platform_device *pdev) | |||
949 | struct atmel_lcdfb_info *sinfo = info->par; | 1054 | struct atmel_lcdfb_info *sinfo = info->par; |
950 | 1055 | ||
951 | atmel_lcdfb_start_clock(sinfo); | 1056 | atmel_lcdfb_start_clock(sinfo); |
1057 | atmel_lcdfb_start(sinfo); | ||
952 | if (sinfo->atmel_lcdfb_power_control) | 1058 | if (sinfo->atmel_lcdfb_power_control) |
953 | sinfo->atmel_lcdfb_power_control(1); | 1059 | sinfo->atmel_lcdfb_power_control(1); |
954 | lcdc_writel(sinfo, ATMEL_LCDC_CONTRAST_CTR, sinfo->saved_lcdcon); | 1060 | lcdc_writel(sinfo, ATMEL_LCDC_CONTRAST_CTR, sinfo->saved_lcdcon); |
1061 | |||
1062 | /* Enable FIFO & DMA errors */ | ||
1063 | lcdc_writel(sinfo, ATMEL_LCDC_IER, ATMEL_LCDC_UFLWI | ||
1064 | | ATMEL_LCDC_OWRI | ATMEL_LCDC_MERI); | ||
1065 | |||
955 | return 0; | 1066 | return 0; |
956 | } | 1067 | } |
957 | 1068 | ||