From ddb5f0fe7d694255237edd3576d39247907d4f3a Mon Sep 17 00:00:00 2001 From: Nirav Patel Date: Tue, 22 May 2012 15:58:55 -0700 Subject: video: tegra: dc: support disp mode override via boot args Allows overidding the default disp mode without having to recompile the kernel. Boot args can be specified in the following format: disp_params=:pclk,h_active,v_active,h_ref_to_sync, v_ref_to_sync,h_sync_width,v_sync_width,h_back_porch,v_back_porch, h_front_porch,v_front_porch;:pclk,h_active,... Bug 969088 Change-Id: Id0acf608de145493f6749d5b799d4bbb8162ba72 Signed-off-by: Nirav Patel Reviewed-on: http://git-master/r/104604 Reviewed-by: Rohan Somvanshi Tested-by: Rohan Somvanshi --- drivers/video/tegra/dc/dc.c | 95 ++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 94 insertions(+), 1 deletion(-) (limited to 'drivers/video/tegra/dc') diff --git a/drivers/video/tegra/dc/dc.c b/drivers/video/tegra/dc/dc.c index e0c4027656f9..77cd19e6f870 100644 --- a/drivers/video/tegra/dc/dc.c +++ b/drivers/video/tegra/dc/dc.c @@ -73,6 +73,8 @@ static struct fb_videomode tegra_dc_hdmi_fallback_mode = { .sync = 0, }; +static struct tegra_dc_mode override_disp_mode[3]; + static void _tegra_dc_controller_disable(struct tegra_dc *dc); struct tegra_dc *tegra_dcs[TEGRA_MAX_DC]; @@ -712,11 +714,27 @@ void tegra_dc_set_out_pin_polars(struct tegra_dc *dc, tegra_dc_writel(dc, pol3, DC_COM_PIN_OUTPUT_POLARITY3); } +static struct tegra_dc_mode *tegra_dc_get_override_mode(struct tegra_dc *dc) +{ + if (dc->out->type == TEGRA_DC_OUT_RGB || + dc->out->type == TEGRA_DC_OUT_HDMI || + dc->out->type == TEGRA_DC_OUT_DSI) + return override_disp_mode[dc->out->type].pclk ? + &override_disp_mode[dc->out->type] : NULL; + else + return NULL; +} + static void tegra_dc_set_out(struct tegra_dc *dc, struct tegra_dc_out *out) { + struct tegra_dc_mode *mode; + dc->out = out; + mode = tegra_dc_get_override_mode(dc); - if (out->n_modes > 0) + if (mode) + tegra_dc_set_mode(dc, mode); + else if (out->n_modes > 0) tegra_dc_set_mode(dc, &dc->out->modes[0]); switch (out->type) { @@ -1609,6 +1627,7 @@ static int tegra_dc_probe(struct nvhost_device *ndev, struct nvhost_device_id *id_table) { struct tegra_dc *dc; + struct tegra_dc_mode *mode; struct clk *clk; struct clk *emc_clk; struct resource *res; @@ -1777,6 +1796,12 @@ static int tegra_dc_probe(struct nvhost_device *ndev, tegra_dc_fmt_bpp(fmt); } + mode = tegra_dc_get_override_mode(dc); + if (mode) { + dc->pdata->fb->xres = mode->h_active; + dc->pdata->fb->yres = mode->v_active; + } + dc->fb = tegra_fb_register(ndev, dc, dc->pdata->fb, fb_mem); if (IS_ERR_OR_NULL(dc->fb)) dc->fb = NULL; @@ -1955,6 +1980,74 @@ struct nvhost_driver tegra_dc_driver = { .shutdown = tegra_dc_shutdown, }; +#ifndef MODULE +static int __init parse_disp_params(char *options, struct tegra_dc_mode *mode) +{ + int i, params[11]; + char *p; + + for (i = 0; i < ARRAY_SIZE(params); i++) { + if ((p = strsep(&options, ",")) != NULL) { + if (*p) + params[i] = simple_strtoul(p, &p, 10); + } else + return -EINVAL; + } + + if ((mode->pclk = params[0]) == 0) + return -EINVAL; + + mode->h_active = params[1]; + mode->v_active = params[2]; + mode->h_ref_to_sync = params[3]; + mode->v_ref_to_sync = params[4]; + mode->h_sync_width = params[5]; + mode->v_sync_width = params[6]; + mode->h_back_porch = params[7]; + mode->v_back_porch = params[8]; + mode->h_front_porch = params[9]; + mode->v_front_porch = params[10]; + + return 0; +} + +static int __init tegra_dc_mode_override(char *str) +{ + char *p = str, *options; + + if (!p || !*p) + return -EINVAL; + + p = strstr(str, "hdmi:"); + if (p) { + p += 5; + options = strsep(&p, ";"); + if (parse_disp_params(options, &override_disp_mode[TEGRA_DC_OUT_HDMI])) + return -EINVAL; + } + + p = strstr(str, "rgb:"); + if (p) { + p += 4; + options = strsep(&p, ";"); + if (parse_disp_params(options, &override_disp_mode[TEGRA_DC_OUT_RGB])) + return -EINVAL; + } + + p = strstr(str, "dsi:"); + if (p) { + p += 4; + options = strsep(&p, ";"); + if (parse_disp_params(options, &override_disp_mode[TEGRA_DC_OUT_DSI])) + return -EINVAL; + } + + return 0; +} + +__setup("disp_params=", tegra_dc_mode_override); +#endif + static int __init tegra_dc_module_init(void) { int ret = tegra_dc_ext_module_init(); -- cgit v1.2.3