summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBhuvanchandra DV <bhuvanchandra.dv@toradex.com>2016-06-15 14:51:00 +0200
committerMax Krummenacher <max.krummenacher@toradex.com>2016-06-27 12:47:47 +0200
commit122acb64708ac40faa8c5755624a0bcfbebcb9e8 (patch)
treeb26aa3560d773ec989740cde7fe6da0947bbec35
parent8524bd40fddfd03e9ee028f430aee5078a0dd431 (diff)
video: mxc: ldb: Add support for LVDS configuration via kernel boot arguments
Add support for LVDS frame buffer configuration via kernel boot arguments. Fix use of the device tree native-mode property. Signed-off-by: Bhuvanchandra DV <bhuvanchandra.dv@toradex.com> Acked-by: Max Krummenacher <max.krummenacher@toradex.com>
-rw-r--r--drivers/video/mxc/ldb.c58
1 files changed, 44 insertions, 14 deletions
diff --git a/drivers/video/mxc/ldb.c b/drivers/video/mxc/ldb.c
index ca533446e7e2..e95959c536de 100644
--- a/drivers/video/mxc/ldb.c
+++ b/drivers/video/mxc/ldb.c
@@ -30,6 +30,7 @@
#include <linux/regmap.h>
#include <linux/types.h>
#include <video/of_videomode.h>
+#include <video/of_display_timing.h>
#include <video/videomode.h>
#include "mxc_dispdrv.h"
@@ -85,7 +86,8 @@ struct ldb_data;
struct ldb_chan {
struct ldb_data *ldb;
struct fb_info *fbi;
- struct videomode vm;
+ unsigned long serial_clk;
+ struct display_timings *timings;
enum crtc crtc;
int chno;
bool is_used;
@@ -309,8 +311,10 @@ static int ldb_init(struct mxc_dispdrv_handle *mddh,
struct device *dev = ldb->dev;
struct fb_info *fbi = setting->fbi;
struct ldb_chan *chan;
- struct fb_videomode fb_vm;
- int chno;
+ struct fb_videomode fb_vm, native_mode;
+ int chno, i, ret;
+ struct videomode vm;
+ unsigned long pixelclock;
chno = ldb->chan[ldb->primary_chno].is_used ?
!ldb->primary_chno : ldb->primary_chno;
@@ -330,13 +334,40 @@ static int ldb_init(struct mxc_dispdrv_handle *mddh,
chan->fbi = fbi;
- fb_videomode_from_videomode(&chan->vm, &fb_vm);
+ setting->crtc = chan->crtc;
INIT_LIST_HEAD(&fbi->modelist);
- fb_add_videomode(&fb_vm, &fbi->modelist);
- fb_videomode_to_var(&fbi->var, &fb_vm);
+ for (i = 0; i < chan->timings->num_timings; i++) {
+ ret = videomode_from_timings(chan->timings, &vm, i);
+ if (ret < 0) {
+ dev_err(ldb->dev,
+ "failed to get video mode from timings\n");
+ return ret;
+ }
- setting->crtc = chan->crtc;
+ ret = fb_videomode_from_videomode(&vm, &fb_vm);
+ if (ret < 0) {
+ dev_err(ldb->dev,
+ "failed to get fb video mode from video mode\n");
+ return ret;
+ }
+
+ if (i == chan->timings->native_mode)
+ fb_videomode_from_videomode(&vm, &native_mode);
+
+ fb_add_videomode(&fb_vm, &fbi->modelist);
+ fb_videomode_to_var(&fbi->var, &fb_vm);
+ }
+
+ fb_find_mode(&fbi->var, fbi, setting->dft_mode_str, &fb_vm,
+ chan->timings->num_timings, &native_mode,
+ setting->default_bpp);
+
+ /* Calculate the LVDS clock */
+ fb_var_to_videomode(&fb_vm, &fbi->var);
+
+ pixelclock = fb_vm.pixclock ? (1000000000UL/(fb_vm.pixclock)) * 1000: 0;
+ chan->serial_clk = ldb->spl_mode ? pixelclock * 7 / 2 : pixelclock * 7;
return 0;
}
@@ -410,7 +441,6 @@ static int ldb_setup(struct mxc_dispdrv_handle *mddh,
struct clk *other_ldb_di_sel = NULL;
struct bus_mux bus_mux;
int ret = 0, id = 0, chno, other_chno;
- unsigned long serial_clk;
u32 mux_val;
ret = find_ldb_chno(ldb, fbi, &chno);
@@ -464,9 +494,7 @@ static int ldb_setup(struct mxc_dispdrv_handle *mddh,
clk_set_parent(ldb->div_sel_clk[chno], ldb_di_parent);
ldb_di_sel = clk_get_parent(ldb_di_parent);
ldb_di_sel_parent = clk_get_parent(ldb_di_sel);
- serial_clk = ldb->spl_mode ? chan.vm.pixelclock * 7 / 2 :
- chan.vm.pixelclock * 7;
- clk_set_rate(ldb_di_sel_parent, serial_clk);
+ clk_set_rate(ldb_di_sel_parent, chan.serial_clk);
/*
* split mode or dual mode:
@@ -845,9 +873,11 @@ static int ldb_probe(struct platform_device *pdev)
return -EINVAL;
}
- ret = of_get_videomode(child, &chan->vm, 0);
- if (ret)
- return -EINVAL;
+ chan->timings = of_get_display_timings(child);
+ if (!chan->timings) {
+ dev_err(ldb->dev, "failed to get display timings\n");
+ ret = -ENOENT;
+ }
sprintf(clkname, "ldb_di%d", i);
ldb->ldb_di_clk[i] = devm_clk_get(dev, clkname);