diff options
author | Liu Ying <Ying.Liu@freescale.com> | 2014-03-24 10:39:01 +0800 |
---|---|---|
committer | Nitin Garg <nitin.garg@freescale.com> | 2014-06-03 23:02:07 -0500 |
commit | 712701a17813a3c149d4a52a7bfa78368c79addf (patch) | |
tree | 6881bcae23859bd016c9e121aa81472b1fee1c51 /drivers | |
parent | 3ef07276ad0d6a16cf42639eda6cad320f4cd017 (diff) |
ENGR00304402 video: mxc LDB: Enable LDB channel after display controller
In order to avoid any random pixelation issue, we should follow a correct
display controller/LDB initialization sequence, that is, LDB channel should
be enabled after its relevant display controller is enabled. Since the
enable() callback of the mxc display driver is called after a display
controller is enabled, this patch uses the enable()/disable() callbacks
to replace the fb notifier callback implemented in the LDB driver. Also,
we disable a LDB channel in the setup() callback of the mxc display driver
to make sure of the correct sequence in any fb set_par() function. As the
enable()/disable() callbacks are always invoked with fb_blank(), this
patch drops the suspend()/resume() functions of the LDB driver which
do nothing but enable/disable LDB channels. We also remove the code to
enable ldb di clocks because they can be enabled when their relevant
child pixel clocks are enabled.
Signed-off-by: Liu Ying <Ying.Liu@freescale.com>
Diffstat (limited to 'drivers')
-rw-r--r-- | drivers/video/mxc/ldb.c | 139 | ||||
-rw-r--r-- | drivers/video/mxc/mipi_dsi.c | 15 | ||||
-rw-r--r-- | drivers/video/mxc/mxc_dispdrv.h | 6 | ||||
-rw-r--r-- | drivers/video/mxc/mxc_ipuv3_fb.c | 6 | ||||
-rw-r--r-- | drivers/video/mxc_hdmi.c | 8 |
5 files changed, 54 insertions, 120 deletions
diff --git a/drivers/video/mxc/ldb.c b/drivers/video/mxc/ldb.c index 19de5c541fdd..12dd03684e0d 100644 --- a/drivers/video/mxc/ldb.c +++ b/drivers/video/mxc/ldb.c @@ -1,5 +1,5 @@ /* - * Copyright (C) 2012-2013 Freescale Semiconductor, Inc. All Rights Reserved. + * Copyright (C) 2012-2014 Freescale Semiconductor, Inc. All Rights Reserved. */ /* @@ -84,7 +84,6 @@ struct ldb_data { uint32_t *reg; uint32_t *control_reg; uint32_t *gpr3_reg; - uint32_t control_reg_data; struct regulator *lvds_bg_reg; int mode; bool inited; @@ -92,13 +91,11 @@ struct ldb_data { struct clk *di_clk; struct clk *ldb_di_clk; bool active; - bool clk_en; int ipu; int di; uint32_t ch_mask; uint32_t ch_val; } setting[2]; - struct notifier_block nb; }; static int g_ldb_mode; @@ -222,7 +219,7 @@ static int find_ldb_setting(struct ldb_data *ldb, struct fb_info *fbi) static int ldb_disp_setup(struct mxc_dispdrv_handle *disp, struct fb_info *fbi) { - uint32_t reg, val; + uint32_t reg; uint32_t pixel_clk, rounded_pixel_clk; struct clk *ldb_clk_parent; struct ldb_data *ldb = mxc_dispdrv_getdata(disp); @@ -234,15 +231,10 @@ static int ldb_disp_setup(struct mxc_dispdrv_handle *disp, struct fb_info *fbi) di = ldb->setting[setting_idx].di; - /* restore channel mode setting */ - val = readl(ldb->control_reg); - val |= ldb->setting[setting_idx].ch_val; - writel(val, ldb->control_reg); - dev_dbg(&ldb->pdev->dev, "LDB setup, control reg:0x%x\n", - readl(ldb->control_reg)); - - /* vsync setup */ reg = readl(ldb->control_reg); + /* clear channel mode */ + reg &= ~ldb->setting[setting_idx].ch_mask; + /* vsync setup */ if (fbi->var.sync & FB_SYNC_VERT_HIGH_ACT) { if (di == 0) reg = (reg & ~LDB_DI0_VS_POL_MASK) @@ -261,8 +253,6 @@ static int ldb_disp_setup(struct mxc_dispdrv_handle *disp, struct fb_info *fbi) writel(reg, ldb->control_reg); /* clk setup */ - if (ldb->setting[setting_idx].clk_en) - clk_disable(ldb->setting[setting_idx].ldb_di_clk); pixel_clk = (PICOS2KHZ(fbi->var.pixclock)) * 1000UL; ldb_clk_parent = clk_get_parent(ldb->setting[setting_idx].ldb_di_clk); if ((ldb->mode == LDB_SPL_DI0) || (ldb->mode == LDB_SPL_DI1)) @@ -272,76 +262,44 @@ static int ldb_disp_setup(struct mxc_dispdrv_handle *disp, struct fb_info *fbi) rounded_pixel_clk = clk_round_rate(ldb->setting[setting_idx].ldb_di_clk, pixel_clk); clk_set_rate(ldb->setting[setting_idx].ldb_di_clk, rounded_pixel_clk); - clk_enable(ldb->setting[setting_idx].ldb_di_clk); - if (!ldb->setting[setting_idx].clk_en) - ldb->setting[setting_idx].clk_en = true; return 0; } -int ldb_fb_event(struct notifier_block *nb, unsigned long val, void *v) +static int ldb_disp_enable(struct mxc_dispdrv_handle *disp, + struct fb_info *fbi) { - struct ldb_data *ldb = container_of(nb, struct ldb_data, nb); - struct fb_event *event = v; - struct fb_info *fbi = event->info; + struct ldb_data *ldb = mxc_dispdrv_getdata(disp); int index; - uint32_t data; + uint32_t reg; index = find_ldb_setting(ldb, fbi); if (index < 0) - return 0; + return index; - fbi->mode = (struct fb_videomode *)fb_match_mode(&fbi->var, - &fbi->modelist); - - if (!fbi->mode) { - dev_warn(&ldb->pdev->dev, - "LDB: can not find mode for xres=%d, yres=%d\n", - fbi->var.xres, fbi->var.yres); - if (ldb->setting[index].clk_en) { - clk_disable(ldb->setting[index].ldb_di_clk); - ldb->setting[index].clk_en = false; - data = readl(ldb->control_reg); - data &= ~ldb->setting[index].ch_mask; - writel(data, ldb->control_reg); - } - return 0; - } + reg = readl(ldb->control_reg); + reg |= ldb->setting[index].ch_val; + writel(reg, ldb->control_reg); - switch (val) { - case FB_EVENT_BLANK: - { - if (*((int *)event->data) == FB_BLANK_UNBLANK) { - if (!ldb->setting[index].clk_en) { - clk_enable(ldb->setting[index].ldb_di_clk); - ldb->setting[index].clk_en = true; - } - } else { - if (ldb->setting[index].clk_en) { - clk_disable(ldb->setting[index].ldb_di_clk); - ldb->setting[index].clk_en = false; - data = readl(ldb->control_reg); - data &= ~ldb->setting[index].ch_mask; - writel(data, ldb->control_reg); - dev_dbg(&ldb->pdev->dev, - "LDB blank, control reg:0x%x\n", - readl(ldb->control_reg)); - } - } - break; - } - case FB_EVENT_SUSPEND: - if (ldb->setting[index].clk_en) { - clk_disable(ldb->setting[index].ldb_di_clk); - ldb->setting[index].clk_en = false; - } - break; - default: - break; - } return 0; } +static void ldb_disp_disable(struct mxc_dispdrv_handle *disp, + struct fb_info *fbi) +{ + struct ldb_data *ldb = mxc_dispdrv_getdata(disp); + int index; + uint32_t reg; + + index = find_ldb_setting(ldb, fbi); + if (index < 0) + return; + + reg = readl(ldb->control_reg); + reg &= ~ldb->setting[index].ch_mask; + writel(reg, ldb->control_reg); +} + #define LVDS_MUX_CTL_WIDTH 2 #define LVDS_MUX_CTL_MASK 3 #define LVDS0_MUX_CTL_OFFS 6 @@ -610,14 +568,6 @@ static int ldb_disp_init(struct mxc_dispdrv_handle *disp, dev_dbg(&ldb->pdev->dev, "ldb_clk to di clk: %s -> %s\n", ldb_clk, di_clk); - /* fb notifier for clk setting */ - ldb->nb.notifier_call = ldb_fb_event, - ret = fb_register_client(&ldb->nb); - if (ret < 0) { - iounmap(ldb->reg); - return ret; - } - ldb->inited = true; } else { /* second time for separate mode */ char di_clk[] = "ipu1_di0_clk"; @@ -754,8 +704,6 @@ static void ldb_disp_deinit(struct mxc_dispdrv_handle *disp) clk_put(ldb->setting[i].ldb_di_clk); } - fb_unregister_client(&ldb->nb); - iounmap(ldb->reg); } @@ -764,33 +712,10 @@ static struct mxc_dispdrv_driver ldb_drv = { .init = ldb_disp_init, .deinit = ldb_disp_deinit, .setup = ldb_disp_setup, + .enable = ldb_disp_enable, + .disable = ldb_disp_disable, }; -static int ldb_suspend(struct platform_device *pdev, pm_message_t state) -{ - struct ldb_data *ldb = dev_get_drvdata(&pdev->dev); - uint32_t data; - - if (!ldb->inited) - return 0; - data = readl(ldb->control_reg); - ldb->control_reg_data = data; - data &= ~(LDB_CH0_MODE_MASK | LDB_CH1_MODE_MASK); - writel(data, ldb->control_reg); - - return 0; -} - -static int ldb_resume(struct platform_device *pdev) -{ - struct ldb_data *ldb = dev_get_drvdata(&pdev->dev); - - if (!ldb->inited) - return 0; - writel(ldb->control_reg_data, ldb->control_reg); - - return 0; -} /*! * This function is called by the driver framework to initialize the LDB * device. @@ -839,8 +764,6 @@ static struct platform_driver mxcldb_driver = { }, .probe = ldb_probe, .remove = ldb_remove, - .suspend = ldb_suspend, - .resume = ldb_resume, }; static int __init ldb_init(void) diff --git a/drivers/video/mxc/mipi_dsi.c b/drivers/video/mxc/mipi_dsi.c index 8434e14f9746..36e5a2e96936 100644 --- a/drivers/video/mxc/mipi_dsi.c +++ b/drivers/video/mxc/mipi_dsi.c @@ -1,5 +1,5 @@ /* - * Copyright (C) 2011-2012 Freescale Semiconductor, Inc. All Rights Reserved. + * Copyright (C) 2011-2014 Freescale Semiconductor, Inc. All Rights Reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -621,7 +621,8 @@ static int mipi_dsi_lcd_init(struct mipi_dsi_info *mipi_dsi, return 0; } -int mipi_dsi_enable(struct mxc_dispdrv_handle *disp) +static int mipi_dsi_enable(struct mxc_dispdrv_handle *disp, + struct fb_info *fbi) { int err; struct mipi_dsi_info *mipi_dsi = mxc_dispdrv_getdata(disp); @@ -649,6 +650,14 @@ int mipi_dsi_enable(struct mxc_dispdrv_handle *disp) return 0; } +static void mipi_dsi_disable(struct mxc_dispdrv_handle *disp, + struct fb_info *fbi) +{ + struct mipi_dsi_info *mipi_dsi = mxc_dispdrv_getdata(disp); + + mipi_dsi_power_off(mipi_dsi->disp_mipi); +} + static int mipi_dsi_disp_init(struct mxc_dispdrv_handle *disp, struct mxc_dispdrv_setting *setting) { @@ -906,7 +915,7 @@ static struct mxc_dispdrv_driver mipi_dsi_drv = { .init = mipi_dsi_disp_init, .deinit = mipi_dsi_disp_deinit, .enable = mipi_dsi_enable, - .disable = mipi_dsi_power_off, + .disable = mipi_dsi_disable, }; /** diff --git a/drivers/video/mxc/mxc_dispdrv.h b/drivers/video/mxc/mxc_dispdrv.h index c6d05fa37799..c9923900bbe8 100644 --- a/drivers/video/mxc/mxc_dispdrv.h +++ b/drivers/video/mxc/mxc_dispdrv.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2011 Freescale Semiconductor, Inc. All Rights Reserved. + * Copyright (C) 2011-2014 Freescale Semiconductor, Inc. All Rights Reserved. */ /* @@ -35,9 +35,9 @@ struct mxc_dispdrv_driver { int (*init) (struct mxc_dispdrv_handle *, struct mxc_dispdrv_setting *); void (*deinit) (struct mxc_dispdrv_handle *); /* display driver enable function for extension */ - int (*enable) (struct mxc_dispdrv_handle *); + int (*enable) (struct mxc_dispdrv_handle *, struct fb_info *); /* display driver disable function, called at early part of fb_blank */ - void (*disable) (struct mxc_dispdrv_handle *); + void (*disable) (struct mxc_dispdrv_handle *, struct fb_info *); /* display driver setup function, called at early part of fb_set_par */ int (*setup) (struct mxc_dispdrv_handle *, struct fb_info *fbi); }; diff --git a/drivers/video/mxc/mxc_ipuv3_fb.c b/drivers/video/mxc/mxc_ipuv3_fb.c index 4c98d51f13b0..bfa588f62d85 100644 --- a/drivers/video/mxc/mxc_ipuv3_fb.c +++ b/drivers/video/mxc/mxc_ipuv3_fb.c @@ -1,5 +1,5 @@ /* - * Copyright 2004-2013 Freescale Semiconductor, Inc. All Rights Reserved. + * Copyright 2004-2014 Freescale Semiconductor, Inc. All Rights Reserved. */ /* @@ -647,7 +647,7 @@ static int mxcfb_set_par(struct fb_info *fbi) ipu_enable_channel(mxc_fbi_fg->ipu, mxc_fbi_fg->ipu_ch); if (mxc_fbi->dispdrv && mxc_fbi->dispdrv->drv->enable) { - retval = mxc_fbi->dispdrv->drv->enable(mxc_fbi->dispdrv); + retval = mxc_fbi->dispdrv->drv->enable(mxc_fbi->dispdrv, fbi); if (retval < 0) { dev_err(fbi->device, "enable error, dispdrv:%s.\n", mxc_fbi->dispdrv->drv->name); @@ -1362,7 +1362,7 @@ static int mxcfb_blank(int blank, struct fb_info *info) case FB_BLANK_HSYNC_SUSPEND: case FB_BLANK_NORMAL: if (mxc_fbi->dispdrv && mxc_fbi->dispdrv->drv->disable) - mxc_fbi->dispdrv->drv->disable(mxc_fbi->dispdrv); + mxc_fbi->dispdrv->drv->disable(mxc_fbi->dispdrv, info); ipu_disable_channel(mxc_fbi->ipu, mxc_fbi->ipu_ch, true); if (mxc_fbi->ipu_di >= 0) ipu_uninit_sync_panel(mxc_fbi->ipu, mxc_fbi->ipu_di); diff --git a/drivers/video/mxc_hdmi.c b/drivers/video/mxc_hdmi.c index c5069aa19eb0..c60c7f381438 100644 --- a/drivers/video/mxc_hdmi.c +++ b/drivers/video/mxc_hdmi.c @@ -1,5 +1,5 @@ /* - * Copyright (C) 2011-2013 Freescale Semiconductor, Inc. + * Copyright (C) 2011-2014 Freescale Semiconductor, Inc. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -1964,14 +1964,16 @@ static void mxc_hdmi_cable_connected(struct mxc_hdmi *hdmi) dev_dbg(&hdmi->pdev->dev, "%s exit\n", __func__); } -static int mxc_hdmi_power_on(struct mxc_dispdrv_handle *disp) +static int mxc_hdmi_power_on(struct mxc_dispdrv_handle *disp, + struct fb_info *fbi) { struct mxc_hdmi *hdmi = mxc_dispdrv_getdata(disp); mxc_hdmi_phy_init(hdmi); return 0; } -static void mxc_hdmi_power_off(struct mxc_dispdrv_handle *disp) +static void mxc_hdmi_power_off(struct mxc_dispdrv_handle *disp, + struct fb_info *fbi) { struct mxc_hdmi *hdmi = mxc_dispdrv_getdata(disp); mxc_hdmi_phy_disable(hdmi); |