summaryrefslogtreecommitdiffstats
path: root/drivers
diff options
context:
space:
mode:
authorSascha Hauer <s.hauer@pengutronix.de>2015-11-20 12:07:03 +0100
committerSascha Hauer <s.hauer@pengutronix.de>2015-11-30 08:22:31 +0100
commit7da99e58bdf6ccf421dacd83e5c9d1231c12507b (patch)
tree496ac1c5231931e7ad391143c2a8a28b8e4569e9 /drivers
parente7a8519963fcb235a123dfe5e7dd59d6fb2eaf9e (diff)
downloadbarebox-7da99e58bdf6ccf421dacd83e5c9d1231c12507b.tar.gz
barebox-7da99e58bdf6ccf421dacd83e5c9d1231c12507b.tar.xz
video: i.MX IPUv3: Set ldb clocks correctly
The clocks for the LVDS display bridge have a fixed /3.5 and a configurable /1,/2 divider in their path. The configurable divider has to be explicitly configured for single/dual channel support, so we can't rely on clock rate parent propagation here. Clear the CLK_SET_RATE_PARENT flag for the configurable divider and configure the clock explicitly in the ldb driver. Tested on a custom i.MX6 board, currently untested on i.MX53. Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de>
Diffstat (limited to 'drivers')
-rw-r--r--drivers/video/imx-ipu-v3/imx-ldb.c26
1 files changed, 22 insertions, 4 deletions
diff --git a/drivers/video/imx-ipu-v3/imx-ldb.c b/drivers/video/imx-ipu-v3/imx-ldb.c
index a41eb1a3fc..2340b9b1d6 100644
--- a/drivers/video/imx-ipu-v3/imx-ldb.c
+++ b/drivers/video/imx-ipu-v3/imx-ldb.c
@@ -68,7 +68,7 @@ struct imx_ldb_channel {
struct imx_ldb_data {
void __iomem *base;
- int (*prepare)(struct imx_ldb_channel *imx_ldb_ch, int di);
+ int (*prepare)(struct imx_ldb_channel *imx_ldb_ch, int di, unsigned long clkrate);
unsigned ipu_mask;
int have_mux;
};
@@ -114,7 +114,7 @@ static int imx_ldb_prepare(struct imx_ldb_channel *imx_ldb_ch, struct fb_videomo
{
struct imx_ldb *ldb = imx_ldb_ch->ldb;
- ldb->soc_data->prepare(imx_ldb_ch, di);
+ ldb->soc_data->prepare(imx_ldb_ch, di, PICOS2KHZ(mode->pixclock) * 1000UL);
/* FIXME - assumes straight connections DI0 --> CH0, DI1 --> CH1 */
if (imx_ldb_ch == &ldb->channel[0]) {
@@ -146,7 +146,8 @@ static int imx_ldb_prepare(struct imx_ldb_channel *imx_ldb_ch, struct fb_videomo
return 0;
}
-static int imx6q_ldb_prepare(struct imx_ldb_channel *imx_ldb_ch, int di)
+static int imx6q_ldb_prepare(struct imx_ldb_channel *imx_ldb_ch, int di,
+ unsigned long pixclk)
{
struct clk *diclk, *ldbclk;
struct imx_ldb *ldb = imx_ldb_ch->ldb;
@@ -155,6 +156,7 @@ static int imx6q_ldb_prepare(struct imx_ldb_channel *imx_ldb_ch, int di)
void __iomem *gpr3 = (void *)MX6_IOMUXC_BASE_ADDR + 0xc;
uint32_t val;
int shift;
+ int dual = ldb->ldb_ctrl & LDB_SPLIT_MODE_EN;
ipuno = ((di >> 1) & 1) + 1;
dino = di & 0x1;
@@ -181,6 +183,11 @@ static int imx6q_ldb_prepare(struct imx_ldb_channel *imx_ldb_ch, int di)
return ret;
}
+ if (!dual)
+ pixclk *= 2;
+
+ clk_set_rate(clk_get_parent(ldbclk), pixclk);
+
val = readl(gpr3);
shift = (imx_ldb_ch->chno == 0) ? 6 : 8;
val &= ~(3 << shift);
@@ -190,12 +197,14 @@ static int imx6q_ldb_prepare(struct imx_ldb_channel *imx_ldb_ch, int di)
return 0;
}
-static int imx53_ldb_prepare(struct imx_ldb_channel *imx_ldb_ch, int di)
+static int imx53_ldb_prepare(struct imx_ldb_channel *imx_ldb_ch, int di,
+ unsigned long pixclk)
{
struct clk *diclk, *ldbclk;
struct imx_ldb *ldb = imx_ldb_ch->ldb;
int ret, dino;
char *clkname;
+ int dual = ldb->ldb_ctrl & LDB_SPLIT_MODE_EN;
dino = di & 0x1;
@@ -221,6 +230,11 @@ static int imx53_ldb_prepare(struct imx_ldb_channel *imx_ldb_ch, int di)
return ret;
}
+ if (!dual)
+ pixclk *= 2;
+
+ clk_set_rate(clk_get_parent(ldbclk), pixclk);
+
return 0;
}
@@ -299,6 +313,10 @@ static int imx_ldb_probe(struct device_d *dev)
imx_ldb->base = devtype->base;
imx_ldb->soc_data = devtype;
+ dual = of_property_read_bool(np, "fsl,dual-channel");
+ if (dual)
+ imx_ldb->ldb_ctrl |= LDB_SPLIT_MODE_EN;
+
for_each_child_of_node(np, child) {
struct imx_ldb_channel *channel;
struct device_node *port;