* 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
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;
#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)
{
}
}
- 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);
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
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;
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;
case FB_BLANK_NORMAL:
if (host->enabled)
mxsfb_disable_controller(fb_info);
+
+ clk_disable_axi(host);
break;
case FB_BLANK_UNBLANK:
if (var->xoffset != 0)
return -EINVAL;
+ clk_enable_axi(host);
+
offset = fb_info->fix.line_length * var->yoffset;
/* update on next VSYNC */
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))
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;
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;
}
fb_destroy:
if (host->enabled)
- clk_disable_unprepare(host->clk);
+ clk_disable_unprepare(host->clk_pix);
fb_release:
framebuffer_release(fb_info);
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 = {