aboutsummaryrefslogtreecommitdiff
path: root/drivers/video/mxc/ldb.c
diff options
context:
space:
mode:
authorJason Chen <jason.chen@linaro.org>2011-12-05 17:41:05 +0800
committerJason Chen <jason.chen@linaro.org>2011-12-06 12:46:18 +0800
commitfaeb3665221aa439d60ea4b03492bd1b9d2d75ac (patch)
tree029ca2810b3e9e43d5e4a56bc7735231c5344bf2 /drivers/video/mxc/ldb.c
parent5e92208bf5080984e18cf042bd2616c55b15100b (diff)
IPU3 FB: merge to fsl imx_2.6.38 branch base
to base commit 433c6306fe9455163cff3591b4cf8e2f22bc6cc8 add ipuv3 fb driver. add mxc display driver. add mxc edid driver. add display device driver for lcd/ldb/tve/dvi/sii902x Signed-off-by: Jason Chen <jason.chen@linaro.org>
Diffstat (limited to 'drivers/video/mxc/ldb.c')
-rw-r--r--drivers/video/mxc/ldb.c138
1 files changed, 134 insertions, 4 deletions
diff --git a/drivers/video/mxc/ldb.c b/drivers/video/mxc/ldb.c
index 180bf7f6f8d..b3a75a5868c 100644
--- a/drivers/video/mxc/ldb.c
+++ b/drivers/video/mxc/ldb.c
@@ -297,6 +297,116 @@ int ldb_fb_event(struct notifier_block *nb, unsigned long val, void *v)
return 0;
}
+#define LVDS0_MUX_CTL_MASK (3 << 6)
+#define LVDS1_MUX_CTL_MASK (3 << 8)
+#define LVDS0_MUX_CTL_OFFS 6
+#define LVDS1_MUX_CTL_OFFS 8
+#define ROUTE_IPU0_DI0 0
+#define ROUTE_IPU0_DI1 1
+#define ROUTE_IPU1_DI0 2
+#define ROUTE_IPU1_DI1 3
+static int ldb_ipu_ldb_route(int ipu, int di, struct ldb_data *ldb)
+{
+ uint32_t reg;
+ int mode = ldb->mode;
+
+ reg = readl(ldb->gpr3_reg);
+ if ((mode == LDB_SPL_DI0) || (mode == LDB_DUL_DI0)) {
+ reg &= ~(LVDS0_MUX_CTL_MASK | LVDS1_MUX_CTL_MASK);
+ if (ipu == 0)
+ reg |= (ROUTE_IPU0_DI0 << LVDS0_MUX_CTL_OFFS) |
+ (ROUTE_IPU0_DI0 << LVDS1_MUX_CTL_OFFS);
+ else
+ reg |= (ROUTE_IPU1_DI0 << LVDS0_MUX_CTL_OFFS) |
+ (ROUTE_IPU1_DI0 << LVDS1_MUX_CTL_OFFS);
+ dev_dbg(&ldb->pdev->dev,
+ "Dual/Split mode both channels route to IPU%d-DI0\n", ipu);
+ } else if ((mode == LDB_SPL_DI1) || (mode == LDB_DUL_DI1)) {
+ reg &= ~(LVDS0_MUX_CTL_MASK | LVDS1_MUX_CTL_MASK);
+ if (ipu == 0)
+ reg |= (ROUTE_IPU0_DI1 << LVDS0_MUX_CTL_OFFS) |
+ (ROUTE_IPU0_DI1 << LVDS1_MUX_CTL_OFFS);
+ else
+ reg |= (ROUTE_IPU1_DI1 << LVDS0_MUX_CTL_OFFS) |
+ (ROUTE_IPU1_DI1 << LVDS1_MUX_CTL_OFFS);
+ dev_dbg(&ldb->pdev->dev,
+ "Dual/Split mode both channels route to IPU%d-DI1\n", ipu);
+ } else if (mode == LDB_SIN0) {
+ reg &= ~LVDS0_MUX_CTL_MASK;
+ if ((ipu == 0) && (di == 0))
+ reg |= ROUTE_IPU0_DI0 << LVDS0_MUX_CTL_OFFS;
+ else if ((ipu == 0) && (di == 1))
+ reg |= ROUTE_IPU0_DI1 << LVDS0_MUX_CTL_OFFS;
+ else if ((ipu == 1) && (di == 0))
+ reg |= ROUTE_IPU1_DI0 << LVDS0_MUX_CTL_OFFS;
+ else
+ reg |= ROUTE_IPU1_DI1 << LVDS0_MUX_CTL_OFFS;
+ dev_dbg(&ldb->pdev->dev,
+ "Single mode channel 0 route to IPU%d-DI%d\n", ipu, di);
+ } else if (mode == LDB_SIN1) {
+ reg &= ~LVDS1_MUX_CTL_MASK;
+ if ((ipu == 0) && (di == 0))
+ reg |= ROUTE_IPU0_DI0 << LVDS1_MUX_CTL_OFFS;
+ else if ((ipu == 0) && (di == 1))
+ reg |= ROUTE_IPU0_DI1 << LVDS1_MUX_CTL_OFFS;
+ else if ((ipu == 1) && (di == 0))
+ reg |= ROUTE_IPU1_DI0 << LVDS1_MUX_CTL_OFFS;
+ else
+ reg |= ROUTE_IPU1_DI1 << LVDS1_MUX_CTL_OFFS;
+ dev_dbg(&ldb->pdev->dev,
+ "Single mode channel 1 route to IPU%d-DI%d\n", ipu, di);
+ } else {
+ static bool first = true;
+ int channel;
+
+ if (first) {
+ if (mode == LDB_SEP0) {
+ reg &= ~LVDS0_MUX_CTL_MASK;
+ channel = 0;
+ } else {
+ reg &= ~LVDS1_MUX_CTL_MASK;
+ channel = 1;
+ }
+ first = false;
+ } else {
+ if (mode == LDB_SEP0) {
+ reg &= ~LVDS1_MUX_CTL_MASK;
+ channel = 1;
+ } else {
+ reg &= ~LVDS0_MUX_CTL_MASK;
+ channel = 0;
+ }
+ }
+
+ if ((ipu == 0) && (di == 0)) {
+ if (channel == 0)
+ reg |= ROUTE_IPU0_DI0 << LVDS0_MUX_CTL_OFFS;
+ else
+ reg |= ROUTE_IPU0_DI0 << LVDS1_MUX_CTL_OFFS;
+ } else if ((ipu == 0) && (di == 1)) {
+ if (channel == 0)
+ reg |= ROUTE_IPU0_DI1 << LVDS0_MUX_CTL_OFFS;
+ else
+ reg |= ROUTE_IPU0_DI1 << LVDS1_MUX_CTL_OFFS;
+ } else if ((ipu == 1) && (di == 0)) {
+ if (channel == 0)
+ reg |= ROUTE_IPU1_DI0 << LVDS0_MUX_CTL_OFFS;
+ else
+ reg |= ROUTE_IPU1_DI0 << LVDS1_MUX_CTL_OFFS;
+ } else {
+ if (channel == 0)
+ reg |= ROUTE_IPU1_DI1 << LVDS0_MUX_CTL_OFFS;
+ else
+ reg |= ROUTE_IPU1_DI1 << LVDS1_MUX_CTL_OFFS;
+ }
+
+ dev_dbg(&ldb->pdev->dev, "Separate mode channel %d route to IPU%d-DI%d\n", channel, ipu, di);
+ }
+ writel(reg, ldb->gpr3_reg);
+
+ return 0;
+}
+
static int ldb_disp_init(struct mxc_dispdrv_entry *disp)
{
int ret = 0, i;
@@ -430,7 +540,11 @@ static int ldb_disp_init(struct mxc_dispdrv_entry *disp)
writel(reg, ldb->control_reg);
/* clock setting */
- ldb_clk[6] += setting->disp_id;
+ if (cpu_is_mx6q() &&
+ ((ldb->mode == LDB_SEP0) || (ldb->mode == LDB_SEP1)))
+ ldb_clk[6] += lvds_channel;
+ else
+ ldb_clk[6] += setting->disp_id;
ldb->ldb_di_clk[0] = clk_get(&ldb->pdev->dev, ldb_clk);
if (IS_ERR(ldb->ldb_di_clk[0])) {
dev_err(&ldb->pdev->dev, "get ldb clk0 failed\n");
@@ -474,8 +588,13 @@ static int ldb_disp_init(struct mxc_dispdrv_entry *disp)
return -EINVAL;
}
- setting->dev_id = plat_data->ipu_id;
- setting->disp_id = !plat_data->disp_id;
+ if (cpu_is_mx6q()) {
+ setting->dev_id = plat_data->sec_ipu_id;
+ setting->disp_id = plat_data->sec_disp_id;
+ } else {
+ setting->dev_id = plat_data->ipu_id;
+ setting->disp_id = !plat_data->disp_id;
+ }
/* second output is LVDS0 or LVDS1 */
if (ldb->mode == LDB_SEP0)
@@ -507,7 +626,10 @@ static int ldb_disp_init(struct mxc_dispdrv_entry *disp)
writel(reg, ldb->control_reg);
/* clock setting */
- ldb_clk[6] += setting->disp_id;
+ if (cpu_is_mx6q())
+ ldb_clk[6] += lvds_channel;
+ else
+ ldb_clk[6] += setting->disp_id;
ldb->ldb_di_clk[1] = clk_get(&ldb->pdev->dev, ldb_clk);
if (IS_ERR(ldb->ldb_di_clk[1])) {
dev_err(&ldb->pdev->dev, "get ldb clk1 failed\n");
@@ -526,6 +648,14 @@ static int ldb_disp_init(struct mxc_dispdrv_entry *disp)
setting_idx = 1;
}
+ if (cpu_is_mx6q()) {
+ 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_ipu_ldb_route(setting->dev_id, setting->disp_id, ldb);
+ }
+
/*
* ldb_di0_clk -> ipux_di0_clk
* ldb_di1_clk -> ipux_di1_clk