]> git.kernelconcepts.de Git - karo-tx-linux.git/commitdiff
ENGR00275031-1 mx6sl fb: support lcdif framebuffer on 3.10
authorRobby Cai <R63905@freescale.com>
Thu, 22 Aug 2013 06:35:09 +0000 (14:35 +0800)
committerLothar Waßmann <LW@KARO-electronics.de>
Wed, 20 Aug 2014 08:06:18 +0000 (10:06 +0200)
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>
Documentation/devicetree/bindings/fb/mxsfb.txt
arch/arm/mach-imx/clk-imx6sl.c
drivers/video/fbdev/mxsfb.c

index 96ec5179c8a00199e2056ee574c3c55aef37bae3..db41376d503e351f09156c2cf28b4e8fb4095d72 100644 (file)
@@ -3,6 +3,9 @@
 Required properties:
 - compatible: Should be "fsl,<chip>-lcdif".  Supported chips include
   imx23 and imx28.
+- pinctrl-names: Should be "default"
+- pinctrl-0: pinctrl setting for lcd
+- lcd-supply: lcd power supply, usually via GPIO
 - reg: Address and length of the register set for lcdif
 - interrupts: Should contain lcdif interrupts
 - display : phandle to display node (see below for details)
@@ -22,6 +25,10 @@ lcdif@80030000 {
        compatible = "fsl,imx28-lcdif";
        reg = <0x80030000 2000>;
        interrupts = <38 86>;
+       pinctrl-names = "default";
+       pinctrl-0 = <&lcdif_24bit_pins_a
+                    &lcdif_pins_evk>;
+       lcd-supply = <&reg_lcd_3v3>;
 
        display: display {
                bits-per-pixel = <32>;
index 5408ca70c8d62ca01cc9d7dbf0fb331b51edec32..bb3750c3e69fd714f164201c56f354af6525e4c1 100644 (file)
@@ -386,5 +386,11 @@ static void __init imx6sl_clocks_init(struct device_node *ccm_node)
 
        np = of_find_compatible_node(NULL, NULL, "fsl,imx6sl-gpt");
        mxc_timer_init_dt(np);
+
+       /* Initialize Video PLLs to valid frequency (650MHz). */
+       clk_set_rate(clks[IMX6SL_CLK_PLL5_VIDEO_DIV], 650000000);
+       /* set PLL5 video as lcdif pix parent clock */
+       clk_set_parent(clks[IMX6SL_CLK_LCDIF_PIX_SEL],
+                       clks[IMX6SL_CLK_PLL5_VIDEO_DIV]);
 }
 CLK_OF_DECLARE(imx6sl, "fsl,imx6sl-ccm", imx6sl_clocks_init);
index accf48a2cce43e16d8ebeea80807df2b32c9cc76..ef4e750578fc309db6948c451030c2d8d78be2d0 100644 (file)
@@ -4,7 +4,7 @@
  * This code is based on:
  * Author: Vitaly Wool <vital@embeddedalley.com>
  *
- * Copyright 2008-2009 Freescale Semiconductor, Inc. All Rights Reserved.
+ * Copyright 2008-2013 Freescale Semiconductor, Inc. All Rights Reserved.
  * Copyright 2008 Embedded Alley Solutions, Inc All Rights Reserved.
  *
  * This program is free software; you can redistribute it and/or
@@ -171,7 +171,9 @@ struct mxsfb_devdata {
 struct mxsfb_info {
        struct fb_info fb_info;
        struct platform_device *pdev;
-       struct clk *clk;
+       struct clk *clk_pix;
+       struct clk *clk_axi;
+       bool clk_axi_enabled;
        void __iomem *base;     /* registers */
        unsigned allocated_size;
        int enabled;
@@ -208,6 +210,26 @@ static const struct mxsfb_devdata mxsfb_devdata[] = {
 
 #define to_imxfb_host(x) (container_of(x, struct mxsfb_info, fb_info))
 
+/* enable lcdif axi clock */
+static inline void clk_enable_axi(struct mxsfb_info *host)
+{
+       if (!host->clk_axi_enabled && host &&
+               host->clk_axi && !IS_ERR(host->clk_axi)) {
+               clk_prepare_enable(host->clk_axi);
+               host->clk_axi_enabled = true;
+       }
+}
+
+/* disable lcdif axi clock */
+static inline void clk_disable_axi(struct mxsfb_info *host)
+{
+       if (host->clk_axi_enabled && host &&
+               host->clk_axi && !IS_ERR(host->clk_axi)) {
+               clk_disable_unprepare(host->clk_axi);
+               host->clk_axi_enabled = false;
+       }
+}
+
 /* mask and shift depends on architecture */
 static inline u32 set_hsync_pulse_width(struct mxsfb_info *host, unsigned val)
 {
@@ -331,8 +353,10 @@ static void mxsfb_enable_controller(struct fb_info *fb_info)
                }
        }
 
-       clk_prepare_enable(host->clk);
-       clk_set_rate(host->clk, PICOS2KHZ(fb_info->var.pixclock) * 1000U);
+       clk_enable_axi(host);
+
+       clk_prepare_enable(host->clk_pix);
+       clk_set_rate(host->clk_pix, PICOS2KHZ(fb_info->var.pixclock) * 1000U);
 
        /* if it was disabled, re-enable the mode again */
        writel(CTRL_DOTCLK_MODE, host->base + LCDC_CTRL + REG_SET);
@@ -356,6 +380,7 @@ static void mxsfb_disable_controller(struct fb_info *fb_info)
 
        dev_dbg(&host->pdev->dev, "%s\n", __func__);
 
+       clk_enable_axi(host);
        /*
         * Even if we disable the controller here, it will still continue
         * until its FIFOs are running out of data
@@ -373,7 +398,7 @@ static void mxsfb_disable_controller(struct fb_info *fb_info)
        reg = readl(host->base + LCDC_VDCTRL4);
        writel(reg & ~VDCTRL4_SYNC_SIGNALS_ON, host->base + LCDC_VDCTRL4);
 
-       clk_disable_unprepare(host->clk);
+       clk_disable_unprepare(host->clk_pix);
 
        host->enabled = 0;
 
@@ -392,6 +417,8 @@ static int mxsfb_set_par(struct fb_info *fb_info)
        int line_size, fb_size;
        int reenable = 0;
 
+       clk_enable_axi(host);
+
        line_size =  fb_info->var.xres * (fb_info->var.bits_per_pixel >> 3);
        fb_size = fb_info->var.yres_virtual * line_size;
 
@@ -550,6 +577,8 @@ static int mxsfb_blank(int blank, struct fb_info *fb_info)
        case FB_BLANK_NORMAL:
                if (host->enabled)
                        mxsfb_disable_controller(fb_info);
+
+               clk_disable_axi(host);
                break;
 
        case FB_BLANK_UNBLANK:
@@ -569,6 +598,8 @@ static int mxsfb_pan_display(struct fb_var_screeninfo *var,
        if (var->xoffset != 0)
                return -EINVAL;
 
+       clk_enable_axi(host);
+
        offset = fb_info->fix.line_length * var->yoffset;
 
        /* update on next VSYNC */
@@ -600,6 +631,8 @@ static int mxsfb_restore_mode(struct mxsfb_info *host,
        int bits_per_pixel, ofs;
        u32 transfer_count, vdctrl0, vdctrl2, vdctrl3, vdctrl4, ctrl;
 
+       clk_enable_axi(host);
+
        /* Only restore the mode when the controller is running */
        ctrl = readl(host->base + LCDC_CTRL);
        if (!(ctrl & CTRL_RUN))
@@ -675,7 +708,7 @@ static int mxsfb_restore_mode(struct mxsfb_info *host,
        line_count = fb_info->fix.smem_len / fb_info->fix.line_length;
        fb_info->fix.ypanstep = 1;
 
-       clk_prepare_enable(host->clk);
+       clk_prepare_enable(host->clk_pix);
        host->enabled = 1;
 
        return 0;
@@ -861,9 +894,15 @@ static int mxsfb_probe(struct platform_device *pdev)
 
        host->devdata = &mxsfb_devdata[pdev->id_entry->driver_data];
 
-       host->clk = devm_clk_get(&host->pdev->dev, NULL);
-       if (IS_ERR(host->clk)) {
-               ret = PTR_ERR(host->clk);
+       host->clk_pix = devm_clk_get(&host->pdev->dev, "pix");
+       if (IS_ERR(host->clk_pix)) {
+               ret = PTR_ERR(host->clk_pix);
+               goto fb_release;
+       }
+
+       host->clk_axi = devm_clk_get(&host->pdev->dev, "axi");
+       if (IS_ERR(host->clk_axi)) {
+               ret = PTR_ERR(host->clk_axi);
                goto fb_release;
        }
 
@@ -907,7 +946,7 @@ static int mxsfb_probe(struct platform_device *pdev)
 
 fb_destroy:
        if (host->enabled)
-               clk_disable_unprepare(host->clk);
+               clk_disable_unprepare(host->clk_pix);
 fb_release:
        framebuffer_release(fb_info);
 
@@ -935,11 +974,13 @@ static void mxsfb_shutdown(struct platform_device *pdev)
        struct fb_info *fb_info = platform_get_drvdata(pdev);
        struct mxsfb_info *host = to_imxfb_host(fb_info);
 
+       clk_enable_axi(host);
        /*
         * Force stop the LCD controller as keeping it running during reboot
         * might interfere with the BootROM's boot mode pads sampling.
         */
        writel(CTRL_RUN, host->base + LCDC_CTRL + REG_CLR);
+       clk_disable_axi(host);
 }
 
 static struct platform_driver mxsfb_driver = {