From 94bd07846f2fc43ab61131c6b07ead4397b47167 Mon Sep 17 00:00:00 2001 From: Wayne Zou Date: Mon, 25 Feb 2013 16:35:09 +0800 Subject: [PATCH] ENGR00251830 LDB: Fix the bug of LDB separate mode for dual LVDS display Fix the bug of LDB separate mode for dual LVDS display on i.mx6. For 'ldb=sep0' option on kernel command line, it means that LVDS0 is the primary display. While 'ldb=sep1' means that LVDS1 is the primary display. For LDB separate mode, the Display Interface(disp_id) should be configured differently on the platform layer. That is, IPU DI0 to LVDS1 or IPU DI1 to LVDS0 configuration should be avoided. Signed-off-by: Wayne Zou --- drivers/video/mxc/ldb.c | 43 ++++++++++++++++++++++++++++------------- 1 file changed, 30 insertions(+), 13 deletions(-) diff --git a/drivers/video/mxc/ldb.c b/drivers/video/mxc/ldb.c index 695ff3389fce..19de5c541fdd 100644 --- a/drivers/video/mxc/ldb.c +++ b/drivers/video/mxc/ldb.c @@ -1,5 +1,5 @@ /* - * Copyright (C) 2012 Freescale Semiconductor, Inc. All Rights Reserved. + * Copyright (C) 2012-2013 Freescale Semiconductor, Inc. All Rights Reserved. */ /* @@ -238,6 +238,8 @@ static int ldb_disp_setup(struct mxc_dispdrv_handle *disp, struct fb_info *fbi) 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); @@ -321,6 +323,9 @@ int ldb_fb_event(struct notifier_block *nb, unsigned long val, void *v) 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; @@ -411,6 +416,7 @@ static int ldb_disp_init(struct mxc_dispdrv_handle *disp, uint32_t base_addr; uint32_t reg, setting_idx; uint32_t ch_mask = 0, ch_val = 0; + uint32_t ipu_id, disp_id; /* if input format not valid, make RGB666 as default*/ if (!valid_mode(setting->if_fmt)) { @@ -479,6 +485,28 @@ static int ldb_disp_init(struct mxc_dispdrv_handle *disp, plat_data->disp_id, ret, ret); plat_data->disp_id = ret; } + } else if (((ldb->mode == LDB_SEP0) || (ldb->mode == LDB_SEP1)) + && (cpu_is_mx6q() || cpu_is_mx6dl())) { + if (plat_data->disp_id == plat_data->sec_disp_id) { + dev_err(&ldb->pdev->dev, + "For LVDS separate mode," + "two DIs should be different!\n"); + return -EINVAL; + } + + if (((!plat_data->disp_id) && (ldb->mode == LDB_SEP1)) + || ((plat_data->disp_id) && + (ldb->mode == LDB_SEP0))) { + dev_dbg(&ldb->pdev->dev, + "LVDS separate mode:" + "swap DI configuration!\n"); + ipu_id = plat_data->ipu_id; + disp_id = plat_data->disp_id; + plat_data->ipu_id = plat_data->sec_ipu_id; + plat_data->disp_id = plat_data->sec_disp_id; + plat_data->sec_ipu_id = ipu_id; + plat_data->sec_disp_id = disp_id; + } } if (ldb->mode == LDB_SPL_DI0) { @@ -679,19 +707,8 @@ static int ldb_disp_init(struct mxc_dispdrv_handle *disp, ldb->setting[setting_idx].ch_mask = ch_mask; ldb->setting[setting_idx].ch_val = ch_val; - if (cpu_is_mx6q() || cpu_is_mx6dl()) { - if ((ldb->mode == LDB_SEP0) || (ldb->mode == LDB_SEP1)) { - reg = readl(ldb->control_reg); - reg &= ~(LDB_CH0_MODE_MASK | LDB_CH1_MODE_MASK); - reg |= LDB_CH0_MODE_EN_TO_DI0 | LDB_CH1_MODE_EN_TO_DI1; - writel(reg, ldb->control_reg); - ldb->setting[setting_idx].ch_mask = setting->disp_id ? - LDB_CH1_MODE_MASK : LDB_CH0_MODE_MASK; - ldb->setting[setting_idx].ch_val = setting->disp_id ? - LDB_CH1_MODE_EN_TO_DI1 : LDB_CH0_MODE_EN_TO_DI0; - } + if (cpu_is_mx6q() || cpu_is_mx6dl()) ldb_ipu_ldb_route(setting->dev_id, setting->disp_id, ldb); - } /* * ldb_di0_clk -> ipux_di0_clk -- 2.39.5