aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/video
diff options
context:
space:
mode:
authorRobby Cai <R63905@freescale.com>2013-08-22 02:35:09 -0400
committerNitin Garg <nitin.garg@freescale.com>2014-04-16 09:01:27 -0400
commit423273b4437f3df3201856afa93fd93e87d44c67 (patch)
tree77a8d420848a2d7102cd42bdb7be98c9567db92b /drivers/video
parentd8a07074df2009874fdad284b8ceedb7244a8a18 (diff)
ENGR00275031-1 mx6sl fb: support lcdif framebuffer on 3.10
re-use the upstreaming mxsfb.c code. - add the lcdif axi clock for register and dram access - set the lcdif pix's parent as pll5_video to get most accurate pix clock - add binding doc for lcdif dts Signed-off-by: Robby Cai <R63905@freescale.com>
Diffstat (limited to 'drivers/video')
-rw-r--r--drivers/video/Kconfig2
-rw-r--r--drivers/video/mxsfb.c63
2 files changed, 53 insertions, 12 deletions
diff --git a/drivers/video/Kconfig b/drivers/video/Kconfig
index 120811cbc063..722208120c84 100644
--- a/drivers/video/Kconfig
+++ b/drivers/video/Kconfig
@@ -2424,7 +2424,7 @@ config FB_JZ4740
2424 2424
2425config FB_MXS 2425config FB_MXS
2426 tristate "MXS LCD framebuffer support" 2426 tristate "MXS LCD framebuffer support"
2427 depends on FB && ARCH_MXS 2427 depends on FB && (ARCH_MXS || ARCH_MXC)
2428 select FB_CFB_FILLRECT 2428 select FB_CFB_FILLRECT
2429 select FB_CFB_COPYAREA 2429 select FB_CFB_COPYAREA
2430 select FB_CFB_IMAGEBLIT 2430 select FB_CFB_IMAGEBLIT
diff --git a/drivers/video/mxsfb.c b/drivers/video/mxsfb.c
index 21223d475b39..5e94efeaa1d2 100644
--- a/drivers/video/mxsfb.c
+++ b/drivers/video/mxsfb.c
@@ -4,7 +4,7 @@
4 * This code is based on: 4 * This code is based on:
5 * Author: Vitaly Wool <vital@embeddedalley.com> 5 * Author: Vitaly Wool <vital@embeddedalley.com>
6 * 6 *
7 * Copyright 2008-2009 Freescale Semiconductor, Inc. All Rights Reserved. 7 * Copyright 2008-2013 Freescale Semiconductor, Inc. All Rights Reserved.
8 * Copyright 2008 Embedded Alley Solutions, Inc All Rights Reserved. 8 * Copyright 2008 Embedded Alley Solutions, Inc All Rights Reserved.
9 * 9 *
10 * This program is free software; you can redistribute it and/or 10 * This program is free software; you can redistribute it and/or
@@ -171,7 +171,9 @@ struct mxsfb_devdata {
171struct mxsfb_info { 171struct mxsfb_info {
172 struct fb_info fb_info; 172 struct fb_info fb_info;
173 struct platform_device *pdev; 173 struct platform_device *pdev;
174 struct clk *clk; 174 struct clk *clk_pix;
175 struct clk *clk_axi;
176 bool clk_axi_enabled;
175 void __iomem *base; /* registers */ 177 void __iomem *base; /* registers */
176 unsigned allocated_size; 178 unsigned allocated_size;
177 int enabled; 179 int enabled;
@@ -208,6 +210,26 @@ static const struct mxsfb_devdata mxsfb_devdata[] = {
208 210
209#define to_imxfb_host(x) (container_of(x, struct mxsfb_info, fb_info)) 211#define to_imxfb_host(x) (container_of(x, struct mxsfb_info, fb_info))
210 212
213/* enable lcdif axi clock */
214static inline void clk_enable_axi(struct mxsfb_info *host)
215{
216 if (!host->clk_axi_enabled && host &&
217 host->clk_axi && !IS_ERR(host->clk_axi)) {
218 clk_prepare_enable(host->clk_axi);
219 host->clk_axi_enabled = true;
220 }
221}
222
223/* disable lcdif axi clock */
224static inline void clk_disable_axi(struct mxsfb_info *host)
225{
226 if (host->clk_axi_enabled && host &&
227 host->clk_axi && !IS_ERR(host->clk_axi)) {
228 clk_disable_unprepare(host->clk_axi);
229 host->clk_axi_enabled = false;
230 }
231}
232
211/* mask and shift depends on architecture */ 233/* mask and shift depends on architecture */
212static inline u32 set_hsync_pulse_width(struct mxsfb_info *host, unsigned val) 234static inline u32 set_hsync_pulse_width(struct mxsfb_info *host, unsigned val)
213{ 235{
@@ -352,8 +374,10 @@ static void mxsfb_enable_controller(struct fb_info *fb_info)
352 } 374 }
353 } 375 }
354 376
355 clk_prepare_enable(host->clk); 377 clk_enable_axi(host);
356 clk_set_rate(host->clk, PICOS2KHZ(fb_info->var.pixclock) * 1000U); 378
379 clk_prepare_enable(host->clk_pix);
380 clk_set_rate(host->clk_pix, PICOS2KHZ(fb_info->var.pixclock) * 1000U);
357 381
358 /* if it was disabled, re-enable the mode again */ 382 /* if it was disabled, re-enable the mode again */
359 writel(CTRL_DOTCLK_MODE, host->base + LCDC_CTRL + REG_SET); 383 writel(CTRL_DOTCLK_MODE, host->base + LCDC_CTRL + REG_SET);
@@ -377,6 +401,7 @@ static void mxsfb_disable_controller(struct fb_info *fb_info)
377 401
378 dev_dbg(&host->pdev->dev, "%s\n", __func__); 402 dev_dbg(&host->pdev->dev, "%s\n", __func__);
379 403
404 clk_enable_axi(host);
380 /* 405 /*
381 * Even if we disable the controller here, it will still continue 406 * Even if we disable the controller here, it will still continue
382 * until its FIFOs are running out of data 407 * until its FIFOs are running out of data
@@ -394,7 +419,7 @@ static void mxsfb_disable_controller(struct fb_info *fb_info)
394 reg = readl(host->base + LCDC_VDCTRL4); 419 reg = readl(host->base + LCDC_VDCTRL4);
395 writel(reg & ~VDCTRL4_SYNC_SIGNALS_ON, host->base + LCDC_VDCTRL4); 420 writel(reg & ~VDCTRL4_SYNC_SIGNALS_ON, host->base + LCDC_VDCTRL4);
396 421
397 clk_disable_unprepare(host->clk); 422 clk_disable_unprepare(host->clk_pix);
398 423
399 host->enabled = 0; 424 host->enabled = 0;
400 425
@@ -413,6 +438,8 @@ static int mxsfb_set_par(struct fb_info *fb_info)
413 int line_size, fb_size; 438 int line_size, fb_size;
414 int reenable = 0; 439 int reenable = 0;
415 440
441 clk_enable_axi(host);
442
416 line_size = fb_info->var.xres * (fb_info->var.bits_per_pixel >> 3); 443 line_size = fb_info->var.xres * (fb_info->var.bits_per_pixel >> 3);
417 fb_size = fb_info->var.yres_virtual * line_size; 444 fb_size = fb_info->var.yres_virtual * line_size;
418 445
@@ -576,6 +603,8 @@ static int mxsfb_blank(int blank, struct fb_info *fb_info)
576 case FB_BLANK_NORMAL: 603 case FB_BLANK_NORMAL:
577 if (host->enabled) 604 if (host->enabled)
578 mxsfb_disable_controller(fb_info); 605 mxsfb_disable_controller(fb_info);
606
607 clk_disable_axi(host);
579 break; 608 break;
580 609
581 case FB_BLANK_UNBLANK: 610 case FB_BLANK_UNBLANK:
@@ -595,6 +624,8 @@ static int mxsfb_pan_display(struct fb_var_screeninfo *var,
595 if (var->xoffset != 0) 624 if (var->xoffset != 0)
596 return -EINVAL; 625 return -EINVAL;
597 626
627 clk_enable_axi(host);
628
598 offset = fb_info->fix.line_length * var->yoffset; 629 offset = fb_info->fix.line_length * var->yoffset;
599 630
600 /* update on next VSYNC */ 631 /* update on next VSYNC */
@@ -626,6 +657,8 @@ static int mxsfb_restore_mode(struct mxsfb_info *host)
626 u32 transfer_count, vdctrl0, vdctrl2, vdctrl3, vdctrl4, ctrl; 657 u32 transfer_count, vdctrl0, vdctrl2, vdctrl3, vdctrl4, ctrl;
627 struct fb_videomode vmode; 658 struct fb_videomode vmode;
628 659
660 clk_enable_axi(host);
661
629 /* Only restore the mode when the controller is running */ 662 /* Only restore the mode when the controller is running */
630 ctrl = readl(host->base + LCDC_CTRL); 663 ctrl = readl(host->base + LCDC_CTRL);
631 if (!(ctrl & CTRL_RUN)) 664 if (!(ctrl & CTRL_RUN))
@@ -654,7 +687,7 @@ static int mxsfb_restore_mode(struct mxsfb_info *host)
654 687
655 fb_info->var.bits_per_pixel = bits_per_pixel; 688 fb_info->var.bits_per_pixel = bits_per_pixel;
656 689
657 vmode.pixclock = KHZ2PICOS(clk_get_rate(host->clk) / 1000U); 690 vmode.pixclock = KHZ2PICOS(clk_get_rate(host->clk_pix) / 1000U);
658 vmode.hsync_len = get_hsync_pulse_width(host, vdctrl2); 691 vmode.hsync_len = get_hsync_pulse_width(host, vdctrl2);
659 vmode.left_margin = GET_HOR_WAIT_CNT(vdctrl3) - vmode.hsync_len; 692 vmode.left_margin = GET_HOR_WAIT_CNT(vdctrl3) - vmode.hsync_len;
660 vmode.right_margin = VDCTRL2_GET_HSYNC_PERIOD(vdctrl2) - vmode.hsync_len - 693 vmode.right_margin = VDCTRL2_GET_HSYNC_PERIOD(vdctrl2) - vmode.hsync_len -
@@ -701,7 +734,7 @@ static int mxsfb_restore_mode(struct mxsfb_info *host)
701 line_count = fb_info->fix.smem_len / fb_info->fix.line_length; 734 line_count = fb_info->fix.smem_len / fb_info->fix.line_length;
702 fb_info->fix.ypanstep = 1; 735 fb_info->fix.ypanstep = 1;
703 736
704 clk_prepare_enable(host->clk); 737 clk_prepare_enable(host->clk_pix);
705 host->enabled = 1; 738 host->enabled = 1;
706 739
707 return 0; 740 return 0;
@@ -915,9 +948,15 @@ static int mxsfb_probe(struct platform_device *pdev)
915 goto fb_release; 948 goto fb_release;
916 } 949 }
917 950
918 host->clk = devm_clk_get(&host->pdev->dev, NULL); 951 host->clk_pix = devm_clk_get(&host->pdev->dev, "pix");
919 if (IS_ERR(host->clk)) { 952 if (IS_ERR(host->clk_pix)) {
920 ret = PTR_ERR(host->clk); 953 ret = PTR_ERR(host->clk_pix);
954 goto fb_release;
955 }
956
957 host->clk_axi = devm_clk_get(&host->pdev->dev, "axi");
958 if (IS_ERR(host->clk_axi)) {
959 ret = PTR_ERR(host->clk_axi);
921 goto fb_release; 960 goto fb_release;
922 } 961 }
923 962
@@ -965,7 +1004,7 @@ static int mxsfb_probe(struct platform_device *pdev)
965 1004
966fb_destroy: 1005fb_destroy:
967 if (host->enabled) 1006 if (host->enabled)
968 clk_disable_unprepare(host->clk); 1007 clk_disable_unprepare(host->clk_pix);
969 fb_destroy_modelist(&fb_info->modelist); 1008 fb_destroy_modelist(&fb_info->modelist);
970fb_release: 1009fb_release:
971 framebuffer_release(fb_info); 1010 framebuffer_release(fb_info);
@@ -996,11 +1035,13 @@ static void mxsfb_shutdown(struct platform_device *pdev)
996 struct fb_info *fb_info = platform_get_drvdata(pdev); 1035 struct fb_info *fb_info = platform_get_drvdata(pdev);
997 struct mxsfb_info *host = to_imxfb_host(fb_info); 1036 struct mxsfb_info *host = to_imxfb_host(fb_info);
998 1037
1038 clk_enable_axi(host);
999 /* 1039 /*
1000 * Force stop the LCD controller as keeping it running during reboot 1040 * Force stop the LCD controller as keeping it running during reboot
1001 * might interfere with the BootROM's boot mode pads sampling. 1041 * might interfere with the BootROM's boot mode pads sampling.
1002 */ 1042 */
1003 writel(CTRL_RUN, host->base + LCDC_CTRL + REG_CLR); 1043 writel(CTRL_RUN, host->base + LCDC_CTRL + REG_CLR);
1044 clk_disable_axi(host);
1004} 1045}
1005 1046
1006static struct platform_driver mxsfb_driver = { 1047static struct platform_driver mxsfb_driver = {