aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/video/fbdev/mxsfb.c68
1 files changed, 54 insertions, 14 deletions
diff --git a/drivers/video/fbdev/mxsfb.c b/drivers/video/fbdev/mxsfb.c
index f8ac4a452f26..0f64165b0147 100644
--- a/drivers/video/fbdev/mxsfb.c
+++ b/drivers/video/fbdev/mxsfb.c
@@ -316,6 +316,18 @@ static int mxsfb_check_var(struct fb_var_screeninfo *var,
316 return 0; 316 return 0;
317} 317}
318 318
319static inline void mxsfb_enable_axi_clk(struct mxsfb_info *host)
320{
321 if (host->clk_axi)
322 clk_prepare_enable(host->clk_axi);
323}
324
325static inline void mxsfb_disable_axi_clk(struct mxsfb_info *host)
326{
327 if (host->clk_axi)
328 clk_disable_unprepare(host->clk_axi);
329}
330
319static void mxsfb_enable_controller(struct fb_info *fb_info) 331static void mxsfb_enable_controller(struct fb_info *fb_info)
320{ 332{
321 struct mxsfb_info *host = to_imxfb_host(fb_info); 333 struct mxsfb_info *host = to_imxfb_host(fb_info);
@@ -333,14 +345,13 @@ static void mxsfb_enable_controller(struct fb_info *fb_info)
333 } 345 }
334 } 346 }
335 347
336 if (host->clk_axi)
337 clk_prepare_enable(host->clk_axi);
338
339 if (host->clk_disp_axi) 348 if (host->clk_disp_axi)
340 clk_prepare_enable(host->clk_disp_axi); 349 clk_prepare_enable(host->clk_disp_axi);
341 clk_prepare_enable(host->clk); 350 clk_prepare_enable(host->clk);
342 clk_set_rate(host->clk, PICOS2KHZ(fb_info->var.pixclock) * 1000U); 351 clk_set_rate(host->clk, PICOS2KHZ(fb_info->var.pixclock) * 1000U);
343 352
353 mxsfb_enable_axi_clk(host);
354
344 /* if it was disabled, re-enable the mode again */ 355 /* if it was disabled, re-enable the mode again */
345 writel(CTRL_DOTCLK_MODE, host->base + LCDC_CTRL + REG_SET); 356 writel(CTRL_DOTCLK_MODE, host->base + LCDC_CTRL + REG_SET);
346 357
@@ -380,11 +391,11 @@ static void mxsfb_disable_controller(struct fb_info *fb_info)
380 reg = readl(host->base + LCDC_VDCTRL4); 391 reg = readl(host->base + LCDC_VDCTRL4);
381 writel(reg & ~VDCTRL4_SYNC_SIGNALS_ON, host->base + LCDC_VDCTRL4); 392 writel(reg & ~VDCTRL4_SYNC_SIGNALS_ON, host->base + LCDC_VDCTRL4);
382 393
394 mxsfb_disable_axi_clk(host);
395
383 clk_disable_unprepare(host->clk); 396 clk_disable_unprepare(host->clk);
384 if (host->clk_disp_axi) 397 if (host->clk_disp_axi)
385 clk_disable_unprepare(host->clk_disp_axi); 398 clk_disable_unprepare(host->clk_disp_axi);
386 if (host->clk_axi)
387 clk_disable_unprepare(host->clk_axi);
388 399
389 host->enabled = 0; 400 host->enabled = 0;
390 401
@@ -421,6 +432,8 @@ static int mxsfb_set_par(struct fb_info *fb_info)
421 mxsfb_disable_controller(fb_info); 432 mxsfb_disable_controller(fb_info);
422 } 433 }
423 434
435 mxsfb_enable_axi_clk(host);
436
424 /* clear the FIFOs */ 437 /* clear the FIFOs */
425 writel(CTRL1_FIFO_CLEAR, host->base + LCDC_CTRL1 + REG_SET); 438 writel(CTRL1_FIFO_CLEAR, host->base + LCDC_CTRL1 + REG_SET);
426 439
@@ -438,6 +451,7 @@ static int mxsfb_set_par(struct fb_info *fb_info)
438 ctrl |= CTRL_SET_WORD_LENGTH(3); 451 ctrl |= CTRL_SET_WORD_LENGTH(3);
439 switch (host->ld_intf_width) { 452 switch (host->ld_intf_width) {
440 case STMLCDIF_8BIT: 453 case STMLCDIF_8BIT:
454 mxsfb_disable_axi_clk(host);
441 dev_err(&host->pdev->dev, 455 dev_err(&host->pdev->dev,
442 "Unsupported LCD bus width mapping\n"); 456 "Unsupported LCD bus width mapping\n");
443 return -EINVAL; 457 return -EINVAL;
@@ -451,6 +465,7 @@ static int mxsfb_set_par(struct fb_info *fb_info)
451 writel(CTRL1_SET_BYTE_PACKAGING(0x7), host->base + LCDC_CTRL1); 465 writel(CTRL1_SET_BYTE_PACKAGING(0x7), host->base + LCDC_CTRL1);
452 break; 466 break;
453 default: 467 default:
468 mxsfb_disable_axi_clk(host);
454 dev_err(&host->pdev->dev, "Unhandled color depth of %u\n", 469 dev_err(&host->pdev->dev, "Unhandled color depth of %u\n",
455 fb_info->var.bits_per_pixel); 470 fb_info->var.bits_per_pixel);
456 return -EINVAL; 471 return -EINVAL;
@@ -504,6 +519,8 @@ static int mxsfb_set_par(struct fb_info *fb_info)
504 fb_info->fix.line_length * fb_info->var.yoffset, 519 fb_info->fix.line_length * fb_info->var.yoffset,
505 host->base + host->devdata->next_buf); 520 host->base + host->devdata->next_buf);
506 521
522 mxsfb_disable_axi_clk(host);
523
507 if (reenable) 524 if (reenable)
508 mxsfb_enable_controller(fb_info); 525 mxsfb_enable_controller(fb_info);
509 526
@@ -582,10 +599,14 @@ static int mxsfb_pan_display(struct fb_var_screeninfo *var,
582 599
583 offset = fb_info->fix.line_length * var->yoffset; 600 offset = fb_info->fix.line_length * var->yoffset;
584 601
602 mxsfb_enable_axi_clk(host);
603
585 /* update on next VSYNC */ 604 /* update on next VSYNC */
586 writel(fb_info->fix.smem_start + offset, 605 writel(fb_info->fix.smem_start + offset,
587 host->base + host->devdata->next_buf); 606 host->base + host->devdata->next_buf);
588 607
608 mxsfb_disable_axi_clk(host);
609
589 return 0; 610 return 0;
590} 611}
591 612
@@ -608,13 +629,17 @@ static int mxsfb_restore_mode(struct mxsfb_info *host,
608 unsigned line_count; 629 unsigned line_count;
609 unsigned period; 630 unsigned period;
610 unsigned long pa, fbsize; 631 unsigned long pa, fbsize;
611 int bits_per_pixel, ofs; 632 int bits_per_pixel, ofs, ret = 0;
612 u32 transfer_count, vdctrl0, vdctrl2, vdctrl3, vdctrl4, ctrl; 633 u32 transfer_count, vdctrl0, vdctrl2, vdctrl3, vdctrl4, ctrl;
613 634
635 mxsfb_enable_axi_clk(host);
636
614 /* Only restore the mode when the controller is running */ 637 /* Only restore the mode when the controller is running */
615 ctrl = readl(host->base + LCDC_CTRL); 638 ctrl = readl(host->base + LCDC_CTRL);
616 if (!(ctrl & CTRL_RUN)) 639 if (!(ctrl & CTRL_RUN)) {
617 return -EINVAL; 640 ret = -EINVAL;
641 goto err;
642 }
618 643
619 vdctrl0 = readl(host->base + LCDC_VDCTRL0); 644 vdctrl0 = readl(host->base + LCDC_VDCTRL0);
620 vdctrl2 = readl(host->base + LCDC_VDCTRL2); 645 vdctrl2 = readl(host->base + LCDC_VDCTRL2);
@@ -635,7 +660,8 @@ static int mxsfb_restore_mode(struct mxsfb_info *host,
635 break; 660 break;
636 case 1: 661 case 1:
637 default: 662 default:
638 return -EINVAL; 663 ret = -EINVAL;
664 goto err;
639 } 665 }
640 666
641 fb_info->var.bits_per_pixel = bits_per_pixel; 667 fb_info->var.bits_per_pixel = bits_per_pixel;
@@ -673,10 +699,14 @@ static int mxsfb_restore_mode(struct mxsfb_info *host,
673 699
674 pa = readl(host->base + host->devdata->cur_buf); 700 pa = readl(host->base + host->devdata->cur_buf);
675 fbsize = fb_info->fix.line_length * vmode->yres; 701 fbsize = fb_info->fix.line_length * vmode->yres;
676 if (pa < fb_info->fix.smem_start) 702 if (pa < fb_info->fix.smem_start) {
677 return -EINVAL; 703 ret = -EINVAL;
678 if (pa + fbsize > fb_info->fix.smem_start + fb_info->fix.smem_len) 704 goto err;
679 return -EINVAL; 705 }
706 if (pa + fbsize > fb_info->fix.smem_start + fb_info->fix.smem_len) {
707 ret = -EINVAL;
708 goto err;
709 }
680 ofs = pa - fb_info->fix.smem_start; 710 ofs = pa - fb_info->fix.smem_start;
681 if (ofs) { 711 if (ofs) {
682 memmove(fb_info->screen_base, fb_info->screen_base + ofs, fbsize); 712 memmove(fb_info->screen_base, fb_info->screen_base + ofs, fbsize);
@@ -689,7 +719,11 @@ static int mxsfb_restore_mode(struct mxsfb_info *host,
689 clk_prepare_enable(host->clk); 719 clk_prepare_enable(host->clk);
690 host->enabled = 1; 720 host->enabled = 1;
691 721
692 return 0; 722err:
723 if (ret)
724 mxsfb_disable_axi_clk(host);
725
726 return ret;
693} 727}
694 728
695static int mxsfb_init_fbinfo_dt(struct mxsfb_info *host, 729static int mxsfb_init_fbinfo_dt(struct mxsfb_info *host,
@@ -915,7 +949,9 @@ static int mxsfb_probe(struct platform_device *pdev)
915 } 949 }
916 950
917 if (!host->enabled) { 951 if (!host->enabled) {
952 mxsfb_enable_axi_clk(host);
918 writel(0, host->base + LCDC_CTRL); 953 writel(0, host->base + LCDC_CTRL);
954 mxsfb_disable_axi_clk(host);
919 mxsfb_set_par(fb_info); 955 mxsfb_set_par(fb_info);
920 mxsfb_enable_controller(fb_info); 956 mxsfb_enable_controller(fb_info);
921 } 957 }
@@ -954,11 +990,15 @@ static void mxsfb_shutdown(struct platform_device *pdev)
954 struct fb_info *fb_info = platform_get_drvdata(pdev); 990 struct fb_info *fb_info = platform_get_drvdata(pdev);
955 struct mxsfb_info *host = to_imxfb_host(fb_info); 991 struct mxsfb_info *host = to_imxfb_host(fb_info);
956 992
993 mxsfb_enable_axi_clk(host);
994
957 /* 995 /*
958 * Force stop the LCD controller as keeping it running during reboot 996 * Force stop the LCD controller as keeping it running during reboot
959 * might interfere with the BootROM's boot mode pads sampling. 997 * might interfere with the BootROM's boot mode pads sampling.
960 */ 998 */
961 writel(CTRL_RUN, host->base + LCDC_CTRL + REG_CLR); 999 writel(CTRL_RUN, host->base + LCDC_CTRL + REG_CLR);
1000
1001 mxsfb_disable_axi_clk(host);
962} 1002}
963 1003
964static struct platform_driver mxsfb_driver = { 1004static struct platform_driver mxsfb_driver = {