diff options
| -rw-r--r-- | drivers/video/atmel_lcdfb.c | 84 |
1 files changed, 49 insertions, 35 deletions
diff --git a/drivers/video/atmel_lcdfb.c b/drivers/video/atmel_lcdfb.c index 5a24c6411d34..75dac578104f 100644 --- a/drivers/video/atmel_lcdfb.c +++ b/drivers/video/atmel_lcdfb.c | |||
| @@ -208,6 +208,36 @@ static unsigned long compute_hozval(unsigned long xres, unsigned long lcdcon2) | |||
| 208 | return value; | 208 | return value; |
| 209 | } | 209 | } |
| 210 | 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 | |||
| 211 | static void atmel_lcdfb_update_dma(struct fb_info *info, | 241 | static void atmel_lcdfb_update_dma(struct fb_info *info, |
| 212 | struct fb_var_screeninfo *var) | 242 | struct fb_var_screeninfo *var) |
| 213 | { | 243 | { |
| @@ -420,26 +450,8 @@ static void atmel_lcdfb_reset(struct atmel_lcdfb_info *sinfo) | |||
| 420 | { | 450 | { |
| 421 | might_sleep(); | 451 | might_sleep(); |
| 422 | 452 | ||
| 423 | /* LCD power off */ | 453 | atmel_lcdfb_stop(sinfo); |
| 424 | lcdc_writel(sinfo, ATMEL_LCDC_PWRCON, sinfo->guard_time << ATMEL_LCDC_GUARDT_OFFSET); | 454 | atmel_lcdfb_start(sinfo); |
| 425 | |||
| 426 | /* wait for the LCDC core to become idle */ | ||
| 427 | while (lcdc_readl(sinfo, ATMEL_LCDC_PWRCON) & ATMEL_LCDC_BUSY) | ||
| 428 | msleep(10); | ||
| 429 | |||
| 430 | /* DMA disable */ | ||
| 431 | lcdc_writel(sinfo, ATMEL_LCDC_DMACON, 0); | ||
| 432 | |||
| 433 | /* wait for DMA engine to become idle */ | ||
| 434 | while (lcdc_readl(sinfo, ATMEL_LCDC_DMACON) & ATMEL_LCDC_DMABUSY) | ||
| 435 | msleep(10); | ||
| 436 | |||
| 437 | /* LCD power on */ | ||
| 438 | lcdc_writel(sinfo, ATMEL_LCDC_PWRCON, | ||
| 439 | (sinfo->guard_time << ATMEL_LCDC_GUARDT_OFFSET) | ATMEL_LCDC_PWR); | ||
| 440 | |||
| 441 | /* DMA enable */ | ||
| 442 | lcdc_writel(sinfo, ATMEL_LCDC_DMACON, sinfo->default_dmacon); | ||
| 443 | } | 455 | } |
| 444 | 456 | ||
| 445 | /** | 457 | /** |
| @@ -471,14 +483,7 @@ static int atmel_lcdfb_set_par(struct fb_info *info) | |||
| 471 | info->var.xres, info->var.yres, | 483 | info->var.xres, info->var.yres, |
| 472 | info->var.xres_virtual, info->var.yres_virtual); | 484 | info->var.xres_virtual, info->var.yres_virtual); |
| 473 | 485 | ||
| 474 | /* Turn off the LCD controller and the DMA controller */ | 486 | atmel_lcdfb_stop_nowait(sinfo); |
| 475 | lcdc_writel(sinfo, ATMEL_LCDC_PWRCON, sinfo->guard_time << ATMEL_LCDC_GUARDT_OFFSET); | ||
| 476 | |||
| 477 | /* Wait for the LCDC core to become idle */ | ||
| 478 | while (lcdc_readl(sinfo, ATMEL_LCDC_PWRCON) & ATMEL_LCDC_BUSY) | ||
| 479 | msleep(10); | ||
| 480 | |||
| 481 | lcdc_writel(sinfo, ATMEL_LCDC_DMACON, 0); | ||
| 482 | 487 | ||
| 483 | if (info->var.bits_per_pixel == 1) | 488 | if (info->var.bits_per_pixel == 1) |
| 484 | info->fix.visual = FB_VISUAL_MONO01; | 489 | info->fix.visual = FB_VISUAL_MONO01; |
| @@ -583,13 +588,7 @@ static int atmel_lcdfb_set_par(struct fb_info *info) | |||
| 583 | while (lcdc_readl(sinfo, ATMEL_LCDC_DMACON) & ATMEL_LCDC_DMABUSY) | 588 | while (lcdc_readl(sinfo, ATMEL_LCDC_DMACON) & ATMEL_LCDC_DMABUSY) |
| 584 | msleep(10); | 589 | msleep(10); |
| 585 | 590 | ||
| 586 | dev_dbg(info->device, " * re-enable DMA engine\n"); | 591 | atmel_lcdfb_start(sinfo); |
| 587 | /* ...and enable it with updated configuration */ | ||
| 588 | lcdc_writel(sinfo, ATMEL_LCDC_DMACON, sinfo->default_dmacon); | ||
| 589 | |||
| 590 | dev_dbg(info->device, " * re-enable LCDC core\n"); | ||
| 591 | lcdc_writel(sinfo, ATMEL_LCDC_PWRCON, | ||
| 592 | (sinfo->guard_time << ATMEL_LCDC_GUARDT_OFFSET) | ATMEL_LCDC_PWR); | ||
| 593 | 592 | ||
| 594 | dev_dbg(info->device, " * DONE\n"); | 593 | dev_dbg(info->device, " * DONE\n"); |
| 595 | 594 | ||
| @@ -1032,11 +1031,20 @@ static int atmel_lcdfb_suspend(struct platform_device *pdev, pm_message_t mesg) | |||
| 1032 | struct fb_info *info = platform_get_drvdata(pdev); | 1031 | struct fb_info *info = platform_get_drvdata(pdev); |
| 1033 | struct atmel_lcdfb_info *sinfo = info->par; | 1032 | struct atmel_lcdfb_info *sinfo = info->par; |
| 1034 | 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 | |||
| 1035 | sinfo->saved_lcdcon = lcdc_readl(sinfo, ATMEL_LCDC_CONTRAST_VAL); | 1040 | sinfo->saved_lcdcon = lcdc_readl(sinfo, ATMEL_LCDC_CONTRAST_VAL); |
| 1036 | lcdc_writel(sinfo, ATMEL_LCDC_CONTRAST_CTR, 0); | 1041 | lcdc_writel(sinfo, ATMEL_LCDC_CONTRAST_CTR, 0); |
| 1037 | if (sinfo->atmel_lcdfb_power_control) | 1042 | if (sinfo->atmel_lcdfb_power_control) |
| 1038 | sinfo->atmel_lcdfb_power_control(0); | 1043 | sinfo->atmel_lcdfb_power_control(0); |
| 1044 | |||
| 1045 | atmel_lcdfb_stop(sinfo); | ||
| 1039 | atmel_lcdfb_stop_clock(sinfo); | 1046 | atmel_lcdfb_stop_clock(sinfo); |
| 1047 | |||
| 1040 | return 0; | 1048 | return 0; |
| 1041 | } | 1049 | } |
| 1042 | 1050 | ||
| @@ -1046,9 +1054,15 @@ static int atmel_lcdfb_resume(struct platform_device *pdev) | |||
| 1046 | struct atmel_lcdfb_info *sinfo = info->par; | 1054 | struct atmel_lcdfb_info *sinfo = info->par; |
| 1047 | 1055 | ||
| 1048 | atmel_lcdfb_start_clock(sinfo); | 1056 | atmel_lcdfb_start_clock(sinfo); |
| 1057 | atmel_lcdfb_start(sinfo); | ||
| 1049 | if (sinfo->atmel_lcdfb_power_control) | 1058 | if (sinfo->atmel_lcdfb_power_control) |
| 1050 | sinfo->atmel_lcdfb_power_control(1); | 1059 | sinfo->atmel_lcdfb_power_control(1); |
| 1051 | 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 | |||
| 1052 | return 0; | 1066 | return 0; |
| 1053 | } | 1067 | } |
| 1054 | 1068 | ||
