diff options
author | Stephen Rothwell <sfr@canb.auug.org.au> | 2011-05-04 11:57:52 +1000 |
---|---|---|
committer | Stephen Rothwell <sfr@canb.auug.org.au> | 2011-05-04 11:57:52 +1000 |
commit | 4375756a830865d240e7c89f58ee7a02f8ca6fb1 (patch) | |
tree | 77e52b2ce1e14ba3b2f61aab99814c1ec0be0dd7 /drivers | |
parent | 1c6dd22ace3f87889a17ea2bb23aea7ed21213d4 (diff) | |
parent | b65b8ccf3106dce84a7c545562952a9ee8c53e24 (diff) |
Merge remote-tracking branch 'omap_dss2/for-next'
Diffstat (limited to 'drivers')
23 files changed, 564 insertions, 379 deletions
diff --git a/drivers/video/omap2/displays/panel-generic-dpi.c b/drivers/video/omap2/displays/panel-generic-dpi.c index 4a9b9ff59467..e359f93fbb1e 100644 --- a/drivers/video/omap2/displays/panel-generic-dpi.c +++ b/drivers/video/omap2/displays/panel-generic-dpi.c @@ -285,7 +285,7 @@ static int generic_dpi_panel_probe(struct omap_dss_device *dssdev) return 0; } -static void generic_dpi_panel_remove(struct omap_dss_device *dssdev) +static void __exit generic_dpi_panel_remove(struct omap_dss_device *dssdev) { struct panel_drv_data *drv_data = dev_get_drvdata(&dssdev->dev); @@ -358,7 +358,7 @@ static int generic_dpi_panel_check_timings(struct omap_dss_device *dssdev, static struct omap_dss_driver dpi_driver = { .probe = generic_dpi_panel_probe, - .remove = generic_dpi_panel_remove, + .remove = __exit_p(generic_dpi_panel_remove), .enable = generic_dpi_panel_enable, .disable = generic_dpi_panel_disable, diff --git a/drivers/video/omap2/displays/panel-sharp-ls037v7dw01.c b/drivers/video/omap2/displays/panel-sharp-ls037v7dw01.c index d2b35d2df2a6..c7727472d6ba 100644 --- a/drivers/video/omap2/displays/panel-sharp-ls037v7dw01.c +++ b/drivers/video/omap2/displays/panel-sharp-ls037v7dw01.c @@ -120,7 +120,7 @@ static int sharp_ls_panel_probe(struct omap_dss_device *dssdev) return 0; } -static void sharp_ls_panel_remove(struct omap_dss_device *dssdev) +static void __exit sharp_ls_panel_remove(struct omap_dss_device *dssdev) { struct sharp_data *sd = dev_get_drvdata(&dssdev->dev); struct backlight_device *bl = sd->bl; @@ -205,7 +205,7 @@ static int sharp_ls_panel_resume(struct omap_dss_device *dssdev) static struct omap_dss_driver sharp_ls_driver = { .probe = sharp_ls_panel_probe, - .remove = sharp_ls_panel_remove, + .remove = __exit_p(sharp_ls_panel_remove), .enable = sharp_ls_panel_enable, .disable = sharp_ls_panel_disable, diff --git a/drivers/video/omap2/displays/panel-taal.c b/drivers/video/omap2/displays/panel-taal.c index adc9900458e1..490998fc6f05 100644 --- a/drivers/video/omap2/displays/panel-taal.c +++ b/drivers/video/omap2/displays/panel-taal.c @@ -819,7 +819,7 @@ err: return r; } -static void taal_remove(struct omap_dss_device *dssdev) +static void __exit taal_remove(struct omap_dss_device *dssdev) { struct taal_data *td = dev_get_drvdata(&dssdev->dev); struct nokia_dsi_panel_data *panel_data = get_panel_data(dssdev); @@ -1557,7 +1557,7 @@ static enum omap_dss_update_mode taal_get_update_mode( static struct omap_dss_driver taal_driver = { .probe = taal_probe, - .remove = taal_remove, + .remove = __exit_p(taal_remove), .enable = taal_enable, .disable = taal_disable, diff --git a/drivers/video/omap2/displays/panel-tpo-td043mtea1.c b/drivers/video/omap2/displays/panel-tpo-td043mtea1.c index dbe9d43b4850..70817847294b 100644 --- a/drivers/video/omap2/displays/panel-tpo-td043mtea1.c +++ b/drivers/video/omap2/displays/panel-tpo-td043mtea1.c @@ -144,13 +144,15 @@ static ssize_t tpo_td043_vmirror_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) { struct tpo_td043_device *tpo_td043 = dev_get_drvdata(dev); - long val; + int val; int ret; - ret = strict_strtol(buf, 0, &val); + ret = kstrtoint(buf, 0, &val); if (ret < 0) return ret; + val = !!val; + ret = tpo_td043_write_mirror(tpo_td043->spi, tpo_td043->hmirror, val); if (ret < 0) return ret; @@ -175,7 +177,7 @@ static ssize_t tpo_td043_mode_store(struct device *dev, long val; int ret; - ret = strict_strtol(buf, 0, &val); + ret = kstrtol(buf, 0, &val); if (ret != 0 || val & ~7) return -EINVAL; diff --git a/drivers/video/omap2/dss/Kconfig b/drivers/video/omap2/dss/Kconfig index bfc5da0e9700..7a49a7514a2e 100644 --- a/drivers/video/omap2/dss/Kconfig +++ b/drivers/video/omap2/dss/Kconfig @@ -90,14 +90,6 @@ config OMAP2_DSS_DSI See http://www.mipi.org/ for DSI spesifications. -config OMAP2_DSS_USE_DSI_PLL - bool "Use DSI PLL for PCLK (EXPERIMENTAL)" - default n - depends on OMAP2_DSS_DSI - help - Use DSI PLL to generate pixel clock. Currently only for DPI output. - DSI PLL can be used to generate higher and more precise pixel clocks. - config OMAP2_DSS_FAKE_VSYNC bool "Fake VSYNC irq from manual update displays" default n @@ -125,4 +117,27 @@ config OMAP2_DSS_MIN_FCK_PER_PCK Max FCK is 173MHz, so this doesn't work if your PCK is very high. +config OMAP2_DSS_SLEEP_BEFORE_RESET + bool "Sleep 50ms before DSS reset" + default y + help + For some unknown reason we may get SYNC_LOST errors from the display + subsystem at initialization time if we don't sleep before resetting + the DSS. See the source (dss.c) for more comments. + + However, 50ms is quite long time to sleep, and with some + configurations the SYNC_LOST may never happen, so the sleep can + be disabled here. + +config OMAP2_DSS_SLEEP_AFTER_VENC_RESET + bool "Sleep 20ms after VENC reset" + default y + help + There is a 20ms sleep after VENC reset which seemed to fix the + reset. The reason for the bug is unclear, and it's also unclear + on what platforms this happens. + + This option enables the sleep, and is enabled by default. You can + disable the sleep if it doesn't cause problems on your platform. + endif diff --git a/drivers/video/omap2/dss/core.c b/drivers/video/omap2/dss/core.c index 1aa2ed1e786e..3584e3ed5126 100644 --- a/drivers/video/omap2/dss/core.c +++ b/drivers/video/omap2/dss/core.c @@ -54,6 +54,9 @@ unsigned int dss_debug; module_param_named(debug, dss_debug, bool, 0644); #endif +static int omap_dss_register_device(struct omap_dss_device *); +static void omap_dss_unregister_device(struct omap_dss_device *); + /* REGULATORS */ struct regulator *dss_get_vdds_dsi(void) @@ -106,7 +109,7 @@ static const struct file_operations dss_debug_fops = { static struct dentry *dss_debugfs_dir; -static int dss_initialize_debugfs(void) +static int __init dss_initialize_debugfs(void) { dss_debugfs_dir = debugfs_create_dir("omapdss", NULL); if (IS_ERR(dss_debugfs_dir)) { @@ -153,7 +156,7 @@ static void dss_uninitialize_debugfs(void) debugfs_remove_recursive(dss_debugfs_dir); } #else /* CONFIG_DEBUG_FS && CONFIG_OMAP2_DSS_DEBUG_SUPPORT */ -static inline int dss_initialize_debugfs(void) +static inline int __init dss_initialize_debugfs(void) { return 0; } @@ -163,7 +166,7 @@ static inline void dss_uninitialize_debugfs(void) #endif /* CONFIG_DEBUG_FS && CONFIG_OMAP2_DSS_DEBUG_SUPPORT */ /* PLATFORM DEVICE */ -static int omap_dss_probe(struct platform_device *pdev) +static int __init omap_dss_probe(struct platform_device *pdev) { struct omap_dss_board_info *pdata = pdev->dev.platform_data; int r; @@ -304,7 +307,6 @@ static int omap_dss_resume(struct platform_device *pdev) } static struct platform_driver omap_dss_driver = { - .probe = omap_dss_probe, .remove = omap_dss_remove, .shutdown = omap_dss_shutdown, .suspend = omap_dss_suspend, @@ -480,7 +482,7 @@ static void omap_dss_dev_release(struct device *dev) reset_device(dev, 0); } -int omap_dss_register_device(struct omap_dss_device *dssdev) +static int __init omap_dss_register_device(struct omap_dss_device *dssdev) { static int dev_num; @@ -494,13 +496,13 @@ int omap_dss_register_device(struct omap_dss_device *dssdev) return device_register(&dssdev->dev); } -void omap_dss_unregister_device(struct omap_dss_device *dssdev) +static void omap_dss_unregister_device(struct omap_dss_device *dssdev) { device_unregister(&dssdev->dev); } /* BUS */ -static int omap_dss_bus_register(void) +static int __init omap_dss_bus_register(void) { int r; @@ -539,7 +541,7 @@ static int __init omap_dss_init(void) if (r) return r; - r = platform_driver_register(&omap_dss_driver); + r = platform_driver_probe(&omap_dss_driver, omap_dss_probe); if (r) { omap_dss_bus_unregister(); return r; @@ -575,7 +577,7 @@ static int __init omap_dss_init(void) static int __init omap_dss_init2(void) { - return platform_driver_register(&omap_dss_driver); + return platform_driver_probe(&omap_dss_driver, omap_dss_probe); } core_initcall(omap_dss_init); diff --git a/drivers/video/omap2/dss/dispc.c b/drivers/video/omap2/dss/dispc.c index 7804779c9da1..4ed2ecfa05c2 100644 --- a/drivers/video/omap2/dss/dispc.c +++ b/drivers/video/omap2/dss/dispc.c @@ -2356,10 +2356,10 @@ unsigned long dispc_fclk_rate(void) unsigned long r = 0; switch (dss_get_dispc_clk_source()) { - case DSS_CLK_SRC_FCK: + case OMAP_DSS_CLK_SRC_FCK: r = dss_clk_get_rate(DSS_CLK_FCK); break; - case DSS_CLK_SRC_DSI_PLL_HSDIV_DISPC: + case OMAP_DSS_CLK_SRC_DSI_PLL_HSDIV_DISPC: r = dsi_get_pll_hsdiv_dispc_rate(); break; default: @@ -2380,10 +2380,10 @@ unsigned long dispc_lclk_rate(enum omap_channel channel) lcd = FLD_GET(l, 23, 16); switch (dss_get_lcd_clk_source(channel)) { - case DSS_CLK_SRC_FCK: + case OMAP_DSS_CLK_SRC_FCK: r = dss_clk_get_rate(DSS_CLK_FCK); break; - case DSS_CLK_SRC_DSI_PLL_HSDIV_DISPC: + case OMAP_DSS_CLK_SRC_DSI_PLL_HSDIV_DISPC: r = dsi_get_pll_hsdiv_dispc_rate(); break; default: @@ -2412,8 +2412,8 @@ void dispc_dump_clocks(struct seq_file *s) { int lcd, pcd; u32 l; - enum dss_clk_source dispc_clk_src = dss_get_dispc_clk_source(); - enum dss_clk_source lcd_clk_src; + enum omap_dss_clk_source dispc_clk_src = dss_get_dispc_clk_source(); + enum omap_dss_clk_source lcd_clk_src; enable_clocks(1); @@ -3419,7 +3419,7 @@ int dispc_setup_plane(enum omap_plane plane, } /* DISPC HW IP initialisation */ -static int omap_dispchw_probe(struct platform_device *pdev) +static int __init omap_dispchw_probe(struct platform_device *pdev) { u32 rev; int r = 0; @@ -3491,7 +3491,6 @@ static int omap_dispchw_remove(struct platform_device *pdev) } static struct platform_driver omap_dispchw_driver = { - .probe = omap_dispchw_probe, .remove = omap_dispchw_remove, .driver = { .name = "omapdss_dispc", @@ -3499,9 +3498,9 @@ static struct platform_driver omap_dispchw_driver = { }, }; -int dispc_init_platform_driver(void) +int __init dispc_init_platform_driver(void) { - return platform_driver_register(&omap_dispchw_driver); + return platform_driver_probe(&omap_dispchw_driver, omap_dispchw_probe); } void dispc_uninit_platform_driver(void) diff --git a/drivers/video/omap2/dss/display.c b/drivers/video/omap2/dss/display.c index a85a6f38b40c..4c9eeba07626 100644 --- a/drivers/video/omap2/dss/display.c +++ b/drivers/video/omap2/dss/display.c @@ -44,9 +44,13 @@ static ssize_t display_enabled_store(struct device *dev, const char *buf, size_t size) { struct omap_dss_device *dssdev = to_dss_device(dev); - bool enabled, r; + int r, enabled; - enabled = simple_strtoul(buf, NULL, 10); + r = kstrtoint(buf, 0, &enabled); + if (r) + return r; + + enabled = !!enabled; if (enabled != (dssdev->state != OMAP_DSS_DISPLAY_DISABLED)) { if (enabled) { @@ -82,7 +86,9 @@ static ssize_t display_upd_mode_store(struct device *dev, if (!dssdev->driver->set_update_mode) return -EINVAL; - val = simple_strtoul(buf, NULL, 10); + r = kstrtoint(buf, 0, &val); + if (r) + return r; switch (val) { case OMAP_DSS_UPDATE_DISABLED: @@ -114,13 +120,16 @@ static ssize_t display_tear_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t size) { struct omap_dss_device *dssdev = to_dss_device(dev); - unsigned long te; - int r; + int te, r; if (!dssdev->driver->enable_te || !dssdev->driver->get_te) return -ENOENT; - te = simple_strtoul(buf, NULL, 0); + r = kstrtoint(buf, 0, &te); + if (r) + return r; + + te = !!te; r = dssdev->driver->enable_te(dssdev, te); if (r) @@ -196,13 +205,14 @@ static ssize_t display_rotate_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t size) { struct omap_dss_device *dssdev = to_dss_device(dev); - unsigned long rot; - int r; + int rot, r; if (!dssdev->driver->set_rotate || !dssdev->driver->get_rotate) return -ENOENT; - rot = simple_strtoul(buf, NULL, 0); + r = kstrtoint(buf, 0, &rot); + if (r) + return r; r = dssdev->driver->set_rotate(dssdev, rot); if (r) @@ -226,13 +236,16 @@ static ssize_t display_mirror_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t size) { struct omap_dss_device *dssdev = to_dss_device(dev); - unsigned long mirror; - int r; + int mirror, r; if (!dssdev->driver->set_mirror || !dssdev->driver->get_mirror) return -ENOENT; - mirror = simple_strtoul(buf, NULL, 0); + r = kstrtoint(buf, 0, &mirror); + if (r) + return r; + + mirror = !!mirror; r = dssdev->driver->set_mirror(dssdev, mirror); if (r) @@ -259,14 +272,15 @@ static ssize_t display_wss_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t size) { struct omap_dss_device *dssdev = to_dss_device(dev); - unsigned long wss; + u32 wss; int r; if (!dssdev->driver->get_wss || !dssdev->driver->set_wss) return -ENOENT; - if (strict_strtoul(buf, 0, &wss)) - return -EINVAL; + r = kstrtou32(buf, 0, &wss); + if (r) + return r; if (wss > 0xfffff) return -EINVAL; diff --git a/drivers/video/omap2/dss/dpi.c b/drivers/video/omap2/dss/dpi.c index 2d3ca4ca4a05..17d28d784cd5 100644 --- a/drivers/video/omap2/dss/dpi.c +++ b/drivers/video/omap2/dss/dpi.c @@ -39,7 +39,17 @@ static struct { struct regulator *vdds_dsi_reg; } dpi; -#ifdef CONFIG_OMAP2_DSS_USE_DSI_PLL +static bool dpi_use_dsi_pll(struct omap_dss_device *dssdev) +{ + if (dssdev->clocks.dispc.dispc_fclk_src == + OMAP_DSS_CLK_SRC_DSI_PLL_HSDIV_DISPC || + dssdev->clocks.dispc.channel.lcd_clk_src == + OMAP_DSS_CLK_SRC_DSI_PLL_HSDIV_DISPC) + return true; + else + return false; +} + static int dpi_set_dsi_clk(struct omap_dss_device *dssdev, bool is_tft, unsigned long pck_req, unsigned long *fck, int *lck_div, int *pck_div) @@ -57,7 +67,7 @@ static int dpi_set_dsi_clk(struct omap_dss_device *dssdev, bool is_tft, if (r) return r; - dss_select_dispc_clk_source(DSS_CLK_SRC_DSI_PLL_HSDIV_DISPC); + dss_select_dispc_clk_source(dssdev->clocks.dispc.dispc_fclk_src); r = dispc_set_clock_div(dssdev->manager->id, &dispc_cinfo); if (r) @@ -69,7 +79,7 @@ static int dpi_set_dsi_clk(struct omap_dss_device *dssdev, bool is_tft, return 0; } -#else + static int dpi_set_dispc_clk(struct omap_dss_device *dssdev, bool is_tft, unsigned long pck_req, unsigned long *fck, int *lck_div, int *pck_div) @@ -96,13 +106,12 @@ static int dpi_set_dispc_clk(struct omap_dss_device *dssdev, bool is_tft, return 0; } -#endif static int dpi_set_mode(struct omap_dss_device *dssdev) { struct omap_video_timings *t = &dssdev->panel.timings; - int lck_div, pck_div; - unsigned long fck; + int lck_div = 0, pck_div = 0; + unsigned long fck = 0; unsigned long pck; bool is_tft; int r = 0; @@ -114,13 +123,12 @@ static int dpi_set_mode(struct omap_dss_device *dssdev) is_tft = (dssdev->panel.config & OMAP_DSS_LCD_TFT) != 0; -#ifdef CONFIG_OMAP2_DSS_USE_DSI_PLL - r = dpi_set_dsi_clk(dssdev, is_tft, t->pixel_clock * 1000, &fck, - &lck_div, &pck_div); -#else - r = dpi_set_dispc_clk(dssdev, is_tft, t->pixel_clock * 1000, &fck, - &lck_div, &pck_div); -#endif + if (dpi_use_dsi_pll(dssdev)) + r = dpi_set_dsi_clk(dssdev, is_tft, t->pixel_clock * 1000, + &fck, &lck_div, &pck_div); + else + r = dpi_set_dispc_clk(dssdev, is_tft, t->pixel_clock * 1000, + &fck, &lck_div, &pck_div); if (r) goto err0; @@ -179,12 +187,13 @@ int omapdss_dpi_display_enable(struct omap_dss_device *dssdev) if (r) goto err2; -#ifdef CONFIG_OMAP2_DSS_USE_DSI_PLL - dss_clk_enable(DSS_CLK_SYSCK); - r = dsi_pll_init(dssdev, 0, 1); - if (r) - goto err3; -#endif + if (dpi_use_dsi_pll(dssdev)) { + dss_clk_enable(DSS_CLK_SYSCK); + r = dsi_pll_init(dssdev, 0, 1); + if (r) + goto err3; + } + r = dpi_set_mode(dssdev); if (r) goto err4; @@ -196,11 +205,11 @@ int omapdss_dpi_display_enable(struct omap_dss_device *dssdev) return 0; err4: -#ifdef CONFIG_OMAP2_DSS_USE_DSI_PLL - dsi_pll_uninit(); + if (dpi_use_dsi_pll(dssdev)) + dsi_pll_uninit(); err3: - dss_clk_disable(DSS_CLK_SYSCK); -#endif + if (dpi_use_dsi_pll(dssdev)) + dss_clk_disable(DSS_CLK_SYSCK); err2: dss_clk_disable(DSS_CLK_ICK | DSS_CLK_FCK); if (cpu_is_omap34xx()) @@ -216,11 +225,11 @@ void omapdss_dpi_display_disable(struct omap_dss_device *dssdev) { dssdev->manager->disable(dssdev->manager); -#ifdef CONFIG_OMAP2_DSS_USE_DSI_PLL - dss_select_dispc_clk_source(DSS_CLK_SRC_FCK); - dsi_pll_uninit(); - dss_clk_disable(DSS_CLK_SYSCK); -#endif + if (dpi_use_dsi_pll(dssdev)) { + dss_select_dispc_clk_source(OMAP_DSS_CLK_SRC_FCK); + dsi_pll_uninit(); + dss_clk_disable(DSS_CLK_SYSCK); + } dss_clk_disable(DSS_CLK_ICK | DSS_CLK_FCK); @@ -251,6 +260,7 @@ int dpi_check_timings(struct omap_dss_device *dssdev, int lck_div, pck_div; unsigned long fck; unsigned long pck; + struct dispc_clock_info dispc_cinfo; if (!dispc_lcd_timings_ok(timings)) return -EINVAL; @@ -260,10 +270,8 @@ int dpi_check_timings(struct omap_dss_device *dssdev, is_tft = (dssdev->panel.config & OMAP_DSS_LCD_TFT) != 0; -#ifdef CONFIG_OMAP2_DSS_USE_DSI_PLL - { + if (dpi_use_dsi_pll(dssdev)) { struct dsi_clock_info dsi_cinfo; - struct dispc_clock_info dispc_cinfo; r = dsi_pll_calc_clock_div_pck(is_tft, timings->pixel_clock * 1000, &dsi_cinfo, &dispc_cinfo); @@ -272,13 +280,8 @@ int dpi_check_timings(struct omap_dss_device *dssdev, return r; fck = dsi_cinfo.dsi_pll_hsdiv_dispc_clk; - lck_div = dispc_cinfo.lck_div; - pck_div = dispc_cinfo.pck_div; - } -#else - { + } else { struct dss_clock_info dss_cinfo; - struct dispc_clock_info dispc_cinfo; r = dss_calc_clock_div(is_tft, timings->pixel_clock * 1000, &dss_cinfo, &dispc_cinfo); @@ -286,10 +289,10 @@ int dpi_check_timings(struct omap_dss_device *dssdev, return r; fck = dss_cinfo.fck; - lck_div = dispc_cinfo.lck_div; - pck_div = dispc_cinfo.pck_div; } -#endif + + lck_div = dispc_cinfo.lck_div; + pck_div = dispc_cinfo.pck_div; pck = fck / lck_div / pck_div / 1000; @@ -319,7 +322,7 @@ int dpi_init_display(struct omap_dss_device *dssdev) return 0; } -int dpi_init(void) +int __init dpi_init(void) { return 0; } diff --git a/drivers/video/omap2/dss/dsi.c b/drivers/video/omap2/dss/dsi.c index cbd9ca48d6ec..2666b6ba6aae 100644 --- a/drivers/video/omap2/dss/dsi.c +++ b/drivers/video/omap2/dss/dsi.c @@ -1009,7 +1009,7 @@ static unsigned long dsi_fclk_rate(void) { unsigned long r; - if (dss_get_dsi_clk_source() == DSS_CLK_SRC_FCK) { + if (dss_get_dsi_clk_source() == OMAP_DSS_CLK_SRC_FCK) { /* DSI FCLK source is DSS_CLK_FCK */ r = dss_clk_get_rate(DSS_CLK_FCK); } else { @@ -1026,7 +1026,7 @@ static int dsi_set_lp_clk_divisor(struct omap_dss_device *dssdev) unsigned lp_clk_div; unsigned long lp_clk; - lp_clk_div = dssdev->phy.dsi.div.lp_clk_div; + lp_clk_div = dssdev->clocks.dsi.lp_clk_div; if (lp_clk_div == 0 || lp_clk_div > dsi.lpdiv_max) return -EINVAL; @@ -1275,7 +1275,7 @@ int dsi_pll_set_clock_div(struct dsi_clock_info *cinfo) { int r = 0; u32 l; - int f; + int f = 0; u8 regn_start, regn_end, regm_start, regm_end; u8 regm_dispc_start, regm_dispc_end, regm_dsi_start, regm_dsi_end; @@ -1317,12 +1317,12 @@ int dsi_pll_set_clock_div(struct dsi_clock_info *cinfo) DSSDBG("Clock lane freq %ld Hz\n", cinfo->clkin4ddr / 4); DSSDBG("regm_dispc = %d, %s (%s) = %lu\n", cinfo->regm_dispc, - dss_get_generic_clk_source_name(DSS_CLK_SRC_DSI_PLL_HSDIV_DISPC), - dss_feat_get_clk_source_name(DSS_CLK_SRC_DSI_PLL_HSDIV_DISPC), + dss_get_generic_clk_source_name(OMAP_DSS_CLK_SRC_DSI_PLL_HSDIV_DISPC), + dss_feat_get_clk_source_name(OMAP_DSS_CLK_SRC_DSI_PLL_HSDIV_DISPC), cinfo->dsi_pll_hsdiv_dispc_clk); DSSDBG("regm_dsi = %d, %s (%s) = %lu\n", cinfo->regm_dsi, - dss_get_generic_clk_source_name(DSS_CLK_SRC_DSI_PLL_HSDIV_DSI), - dss_feat_get_clk_source_name(DSS_CLK_SRC_DSI_PLL_HSDIV_DSI), + dss_get_generic_clk_source_name(OMAP_DSS_CLK_SRC_DSI_PLL_HSDIV_DSI), + dss_feat_get_clk_source_name(OMAP_DSS_CLK_SRC_DSI_PLL_HSDIV_DSI), cinfo->dsi_pll_hsdiv_dsi_clk); dss_feat_get_reg_field(FEAT_REG_DSIPLL_REGN, ®n_start, ®n_end); @@ -1349,19 +1349,19 @@ int dsi_pll_set_clock_div(struct dsi_clock_info *cinfo) dsi_write_reg(DSI_PLL_CONFIGURATION1, l); BUG_ON(cinfo->fint < dsi.fint_min || cinfo->fint > dsi.fint_max); - if (cinfo->fint < 1000000) - f = 0x3; - else if (cinfo->fint < 1250000) - f = 0x4; - else if (cinfo->fint < 1500000) - f = 0x5; - else if (cinfo->fint < 1750000) - f = 0x6; - else - f = 0x7; + + if (dss_has_feature(FEAT_DSI_PLL_FREQSEL)) { + f = cinfo->fint < 1000000 ? 0x3 : + cinfo->fint < 1250000 ? 0x4 : + cinfo->fint < 1500000 ? 0x5 : + cinfo->fint < 1750000 ? 0x6 : + 0x7; + } l = dsi_read_reg(DSI_PLL_CONFIGURATION2); - l = FLD_MOD(l, f, 4, 1); /* DSI_PLL_FREQSEL */ + + if (dss_has_feature(FEAT_DSI_PLL_FREQSEL)) + l = FLD_MOD(l, f, 4, 1); /* DSI_PLL_FREQSEL */ l = FLD_MOD(l, cinfo->use_sys_clk ? 0 : 1, 11, 11); /* DSI_PLL_CLKSEL */ l = FLD_MOD(l, cinfo->highfreq, @@ -1417,12 +1417,6 @@ int dsi_pll_init(struct omap_dss_device *dssdev, bool enable_hsclk, DSSDBG("PLL init\n"); -#ifdef CONFIG_OMAP2_DSS_USE_DSI_PLL - /* - * HACK: this is just a quick hack to get the USE_DSI_PLL - * option working. USE_DSI_PLL is itself a big hack, and - * should be removed. - */ if (dsi.vdds_dsi_reg == NULL) { struct regulator *vdds_dsi; @@ -1435,7 +1429,6 @@ int dsi_pll_init(struct omap_dss_device *dssdev, bool enable_hsclk, dsi.vdds_dsi_reg = vdds_dsi; } -#endif enable_clocks(1); dsi_enable_pll_clock(1); @@ -1497,7 +1490,7 @@ void dsi_pll_uninit(void) void dsi_dump_clocks(struct seq_file *s) { struct dsi_clock_info *cinfo = &dsi.current_cinfo; - enum dss_clk_source dispc_clk_src, dsi_clk_src; + enum omap_dss_clk_source dispc_clk_src, dsi_clk_src; dispc_clk_src = dss_get_dispc_clk_source(); dsi_clk_src = dss_get_dsi_clk_source(); @@ -1519,7 +1512,7 @@ void dsi_dump_clocks(struct seq_file *s) dss_feat_get_clk_source_name(dispc_clk_src), cinfo->dsi_pll_hsdiv_dispc_clk, cinfo->regm_dispc, - dispc_clk_src == DSS_CLK_SRC_FCK ? + dispc_clk_src == OMAP_DSS_CLK_SRC_FCK ? "off" : "on"); seq_printf(s, "%s (%s)\t%-16luregm_dsi %u\t(%s)\n", @@ -1527,7 +1520,7 @@ void dsi_dump_clocks(struct seq_file *s) dss_feat_get_clk_source_name(dsi_clk_src), cinfo->dsi_pll_hsdiv_dsi_clk, cinfo->regm_dsi, - dsi_clk_src == DSS_CLK_SRC_FCK ? + dsi_clk_src == OMAP_DSS_CLK_SRC_FCK ? "off" : "on"); seq_printf(s, "- DSI -\n"); @@ -1877,9 +1870,6 @@ static int dsi_complexio_init(struct omap_dss_device *dssdev) DSSDBG("dsi_complexio_init\n"); - /* CIO_CLK_ICG, enable L3 clk to CIO */ - REG_FLD_MOD(DSI_CLK_CTRL, 1, 14, 14); - /* A dummy read using the SCP interface to any DSIPHY register is * required after DSIPHY reset to complete the reset of the DSI complex * I/O. */ @@ -1904,10 +1894,12 @@ static int dsi_complexio_init(struct omap_dss_device *dssdev) goto err; } - if (wait_for_bit_change(DSI_COMPLEXIO_CFG1, 21, 1) != 1) { - DSSERR("ComplexIO LDO power down.\n"); - r = -ENODEV; - goto err; + if (dss_has_feature(FEAT_DSI_LDO_STATUS)) { + if (wait_for_bit_change(DSI_COMPLEXIO_CFG1, 21, 1) != 1) { + DSSERR("ComplexIO LDO power down.\n"); + r = -ENODEV; + goto err; + } } dsi_complexio_timings(); @@ -2038,6 +2030,114 @@ static int dsi_force_tx_stop_mode_io(void) return 0; } +static bool dsi_vc_is_enabled(int channel) +{ + return REG_GET(DSI_VC_CTRL(channel), 0, 0); +} + +static void dsi_packet_sent_handler_vp(void *data, u32 mask) +{ + const int channel = dsi.update_channel; + u8 bit = dsi.te_enabled ? 30 : 31; + + if (REG_GET(DSI_VC_TE(channel), bit, bit) == 0) + complete((struct completion *)data); +} + +static int dsi_sync_vc_vp(int channel) +{ + int r = 0; + u8 bit; + + DECLARE_COMPLETION_ONSTACK(completion); + + bit = dsi.te_enabled ? 30 : 31; + + r = dsi_register_isr_vc(channel, dsi_packet_sent_handler_vp, + &completion, DSI_VC_IRQ_PACKET_SENT); + if (r) + goto err0; + + /* Wait for completion only if TE_EN/TE_START is still set */ + if (REG_GET(DSI_VC_TE(channel), bit, bit)) { + if (wait_for_completion_timeout(&completion, + msecs_to_jiffies(10)) == 0) { + DSSERR("Failed to complete previous frame transfer\n"); + r = -EIO; + goto err1; + } + } + + dsi_unregister_isr_vc(channel, dsi_packet_sent_handler_vp, + &completion, DSI_VC_IRQ_PACKET_SENT); + + return 0; +err1: + dsi_unregister_isr_vc(channel, dsi_packet_sent_handler_vp, &completion, + DSI_VC_IRQ_PACKET_SENT); +err0: + return r; +} + +static void dsi_packet_sent_handler_l4(void *data, u32 mask) +{ + const int channel = dsi.update_channel; + + if (REG_GET(DSI_VC_CTRL(channel), 5, 5) == 0) + complete((struct completion *)data); +} + +static int dsi_sync_vc_l4(int channel) +{ + int r = 0; + + DECLARE_COMPLETION_ONSTACK(completion); + + r = dsi_register_isr_vc(channel, dsi_packet_sent_handler_l4, + &completion, DSI_VC_IRQ_PACKET_SENT); + if (r) + goto err0; + + /* Wait for completion only if TX_FIFO_NOT_EMPTY is still set */ + if (REG_GET(DSI_VC_CTRL(channel), 5, 5)) { + if (wait_for_completion_timeout(&completion, + msecs_to_jiffies(10)) == 0) { + DSSERR("Failed to complete previous l4 transfer\n"); + r = -EIO; + goto err1; + } + } + + dsi_unregister_isr_vc(channel, dsi_packet_sent_handler_l4, + &completion, DSI_VC_IRQ_PACKET_SENT); + + return 0; +err1: + dsi_unregister_isr_vc(channel, dsi_packet_sent_handler_l4, + &completion, DSI_VC_IRQ_PACKET_SENT); +err0: + return r; +} + +static int dsi_sync_vc(int channel) +{ + WARN_ON(!dsi_bus_is_locked()); + + WARN_ON(in_interrupt()); + + if (!dsi_vc_is_enabled(channel)) + return 0; + + switch (dsi.vc[channel].mode) { + case DSI_VC_MODE_VP: + return dsi_sync_vc_vp(channel); + case DSI_VC_MODE_L4: + return dsi_sync_vc_l4(channel); + default: + BUG(); + } +} + static int dsi_vc_enable(int channel, bool enable) { DSSDBG("dsi_vc_enable channel %d, enable %d\n", @@ -2074,6 +2174,8 @@ static void dsi_vc_initial_config(int channel) r = FLD_MOD(r, 1, 7, 7); /* CS_TX_EN */ r = FLD_MOD(r, 1, 8, 8); /* ECC_TX_EN */ r = FLD_MOD(r, 0, 9, 9); /* MODE_SPEED, high speed on/off */ + if (dss_has_feature(FEAT_DSI_VC_OCP_WIDTH)) + r = FLD_MOD(r, 3, 11, 10); /* OCP_WIDTH = 32 bit */ r = FLD_MOD(r, 4, 29, 27); /* DMA_RX_REQ_NB = no dma */ r = FLD_MOD(r, 4, 23, 21); /* DMA_TX_REQ_NB = no dma */ @@ -2088,6 +2190,8 @@ static int dsi_vc_config_l4(int channel) DSSDBGF("%d", channel); + dsi_sync_vc(channel); + dsi_vc_enable(channel, 0); /* VC_BUSY */ @@ -2098,6 +2202,10 @@ static int dsi_vc_config_l4(int channel) REG_FLD_MOD(DSI_VC_CTRL(channel), 0, 1, 1); /* SOURCE, 0 = L4 */ + /* DCS_CMD_ENABLE */ + if (dss_has_feature(FEAT_DSI_DCS_CMD_CONFIG_VC)) + REG_FLD_MOD(DSI_VC_CTRL(channel), 0, 30, 30); + dsi_vc_enable(channel, 1); dsi.vc[channel].mode = DSI_VC_MODE_L4; @@ -2112,6 +2220,8 @@ static int dsi_vc_config_vp(int channel) DSSDBGF("%d", channel); + dsi_sync_vc(channel); + dsi_vc_enable(channel, 0); /* VC_BUSY */ @@ -2122,6 +2232,10 @@ static int dsi_vc_config_vp(int channel) REG_FLD_MOD(DSI_VC_CTRL(channel), 1, 1, 1); /* SOURCE, 1 = video port */ + /* DCS_CMD_ENABLE */ + if (dss_has_feature(FEAT_DSI_DCS_CMD_CONFIG_VC)) + REG_FLD_MOD(DSI_VC_CTRL(channel), 1, 30, 30); + dsi_vc_enable(channel, 1); dsi.vc[channel].mode = DSI_VC_MODE_VP; @@ -2777,8 +2891,11 @@ static int dsi_proto_config(struct omap_dss_device *dssdev) r = FLD_MOD(r, 2, 13, 12); /* LINE_BUFFER, 2 lines */ r = FLD_MOD(r, 1, 14, 14); /* TRIGGER_RESET_MODE */ r = FLD_MOD(r, 1, 19, 19); /* EOT_ENABLE */ - r = FLD_MOD(r, 1, 24, 24); /* DCS_CMD_ENABLE */ - r = FLD_MOD(r, 0, 25, 25); /* DCS_CMD_CODE, 1=start, 0=continue */ + if (!dss_has_feature(FEAT_DSI_DCS_CMD_CONFIG_VC)) { + r = FLD_MOD(r, 1, 24, 24); /* DCS_CMD_ENABLE */ + /* DCS_CMD_CODE, 1=start, 0=continue */ + r = FLD_MOD(r, 0, 25, 25); + } dsi_write_reg(DSI_CTRL, r); @@ -3097,17 +3214,8 @@ static void dsi_te_timeout(unsigned long arg) } #endif -static void dsi_framedone_bta_callback(void *data, u32 mask); - static void dsi_handle_framedone(int error) { - const int channel = dsi.update_channel; - - dsi_unregister_isr_vc(channel, dsi_framedone_bta_callback, - NULL, DSI_VC_IRQ_BTA); - - cancel_delayed_work(&dsi.framedone_timeout_work); - /* SIDLEMODE back to smart-idle */ dispc_enable_sidle(); @@ -3116,14 +3224,6 @@ static void dsi_handle_framedone(int error) REG_FLD_MOD(DSI_TIMING2, 1, 15, 15); /* LP_RX_TO */ } - /* RX_FIFO_NOT_EMPTY */ - if (REG_GET(DSI_VC_CTRL(channel), 20, 20)) { - DSSERR("Received error during frame transfer:\n"); - dsi_vc_flush_receive_data(channel); - if (!error) - error = -EIO; - } - dsi.framedone_callback(error, dsi.framedone_data); if (!error) @@ -3144,61 +3244,20 @@ static void dsi_framedone_timeout_work_callback(struct work_struct *work) dsi_handle_framedone(-ETIMEDOUT); } -static void dsi_framedone_bta_callback(void *data, u32 mask) -{ - dsi_handle_framedone(0); - -#ifdef CONFIG_OMAP2_DSS_FAKE_VSYNC - dispc_fake_vsync_irq(); -#endif -} - static void dsi_framedone_irq_callback(void *data, u32 mask) { - const int channel = dsi.update_channel; - int r; - /* Note: We get FRAMEDONE when DISPC has finished sending pixels and * turns itself off. However, DSI still has the pixels in its buffers, * and is sending the data. */ - if (dsi.te_enabled) { - /* enable LP_RX_TO again after the TE */ - REG_FLD_MOD(DSI_TIMING2, 1, 15, 15); /* LP_RX_TO */ - } + __cancel_delayed_work(&dsi.framedone_timeout_work); - /* Send BTA after the frame. We need this for the TE to work, as TE - * trigger is only sent for BTAs without preceding packet. Thus we need - * to BTA after the pixel packets so that next BTA will cause TE - * trigger. - * - * This is not needed when TE is not in use, but we do it anyway to - * make sure that the transfer has been completed. It would be more - * optimal, but more complex, to wait only just before starting next - * transfer. - * - * Also, as there's no interrupt telling when the transfer has been - * done and the channel could be reconfigured, the only way is to - * busyloop until TE_SIZE is zero. With BTA we can do this - * asynchronously. - * */ - - r = dsi_register_isr_vc(channel, dsi_framedone_bta_callback, - NULL, DSI_VC_IRQ_BTA); - if (r) { - DSSERR("Failed to register BTA ISR\n"); - dsi_handle_framedone(-EIO); - return; - } + dsi_handle_framedone(0); - r = dsi_vc_send_bta(channel); - if (r) { - DSSERR("BTA after framedone failed\n"); - dsi_unregister_isr_vc(channel, dsi_framedone_bta_callback, - NULL, DSI_VC_IRQ_BTA); - dsi_handle_framedone(-EIO); - } +#ifdef CONFIG_OMAP2_DSS_FAKE_VSYNC + dispc_fake_vsync_irq(); +#endif } int omap_dsi_prepare_update(struct omap_dss_device *dssdev, @@ -3326,10 +3385,10 @@ static int dsi_configure_dsi_clocks(struct omap_dss_device *dssdev) /* we always use DSS_CLK_SYSCK as input clock */ cinfo.use_sys_clk = true; - cinfo.regn = dssdev->phy.dsi.div.regn; - cinfo.regm = dssdev->phy.dsi.div.regm; - cinfo.regm_dispc = dssdev->phy.dsi.div.regm_dispc; - cinfo.regm_dsi = dssdev->phy.dsi.div.regm_dsi; + cinfo.regn = dssdev->clocks.dsi.regn; + cinfo.regm = dssdev->clocks.dsi.regm; + cinfo.regm_dispc = dssdev->clocks.dsi.regm_dispc; + cinfo.regm_dsi = dssdev->clocks.dsi.regm_dsi; r = dsi_calc_clock_rates(dssdev, &cinfo); if (r) { DSSERR("Failed to calc dsi clocks\n"); @@ -3353,8 +3412,8 @@ static int dsi_configure_dispc_clocks(struct omap_dss_device *dssdev) fck = dsi_get_pll_hsdiv_dispc_rate(); - dispc_cinfo.lck_div = dssdev->phy.dsi.div.lck_div; - dispc_cinfo.pck_div = dssdev->phy.dsi.div.pck_div; + dispc_cinfo.lck_div = dssdev->clocks.dispc.channel.lck_div; + dispc_cinfo.pck_div = dssdev->clocks.dispc.channel.pck_div; r = dispc_calc_clock_rates(fck, &dispc_cinfo); if (r) { @@ -3375,6 +3434,10 @@ static int dsi_display_init_dsi(struct omap_dss_device *dssdev) { int r; + /* The SCPClk is required for both PLL and CIO registers on OMAP4 */ + /* CIO_CLK_ICG, enable L3 clk to CIO */ + REG_FLD_MOD(DSI_CLK_CTRL, 1, 14, 14); + _dsi_print_reset_status(); r = dsi_pll_init(dssdev, true, true); @@ -3385,8 +3448,10 @@ static int dsi_display_init_dsi(struct omap_dss_device *dssdev) if (r) goto err1; - dss_select_dispc_clk_source(DSS_CLK_SRC_DSI_PLL_HSDIV_DISPC); - dss_select_dsi_clk_source(DSS_CLK_SRC_DSI_PLL_HSDIV_DSI); + dss_select_dispc_clk_source(dssdev->clocks.dispc.dispc_fclk_src); + dss_select_dsi_clk_source(dssdev->clocks.dsi.dsi_fclk_src); + dss_select_lcd_clk_source(dssdev->manager->id, + dssdev->clocks.dispc.channel.lcd_clk_src); DSSDBG("PLL OK\n"); @@ -3422,8 +3487,8 @@ static int dsi_display_init_dsi(struct omap_dss_device *dssdev) err3: dsi_complexio_uninit(); err2: - dss_select_dispc_clk_source(DSS_CLK_SRC_FCK); - dss_select_dsi_clk_source(DSS_CLK_SRC_FCK); + dss_select_dispc_clk_source(OMAP_DSS_CLK_SRC_FCK); + dss_select_dsi_clk_source(OMAP_DSS_CLK_SRC_FCK); err1: dsi_pll_uninit(); err0: @@ -3439,8 +3504,8 @@ static void dsi_display_uninit_dsi(struct omap_dss_device *dssdev) dsi_vc_enable(2, 0); dsi_vc_enable(3, 0); - dss_select_dispc_clk_source(DSS_CLK_SRC_FCK); - dss_select_dsi_clk_source(DSS_CLK_SRC_FCK); + dss_select_dispc_clk_source(OMAP_DSS_CLK_SRC_FCK); + dss_select_dsi_clk_source(OMAP_DSS_CLK_SRC_FCK); dsi_complexio_uninit(); dsi_pll_uninit(); } @@ -3631,16 +3696,16 @@ void dsi_wait_pll_hsdiv_dispc_active(void) { if (wait_for_bit_change(DSI_PLL_STATUS, 7, 1) != 1) DSSERR("%s (%s) not active\n", - dss_get_generic_clk_source_name(DSS_CLK_SRC_DSI_PLL_HSDIV_DISPC), - dss_feat_get_clk_source_name(DSS_CLK_SRC_DSI_PLL_HSDIV_DISPC)); + dss_get_generic_clk_source_name(OMAP_DSS_CLK_SRC_DSI_PLL_HSDIV_DISPC), + dss_feat_get_clk_source_name(OMAP_DSS_CLK_SRC_DSI_PLL_HSDIV_DISPC)); } void dsi_wait_pll_hsdiv_dsi_active(void) { if (wait_for_bit_change(DSI_PLL_STATUS, 8, 1) != 1) DSSERR("%s (%s) not active\n", - dss_get_generic_clk_source_name(DSS_CLK_SRC_DSI_PLL_HSDIV_DSI), - dss_feat_get_clk_source_name(DSS_CLK_SRC_DSI_PLL_HSDIV_DSI)); + dss_get_generic_clk_source_name(OMAP_DSS_CLK_SRC_DSI_PLL_HSDIV_DSI), + dss_feat_get_clk_source_name(OMAP_DSS_CLK_SRC_DSI_PLL_HSDIV_DSI)); } static void dsi_calc_clock_param_ranges(void) @@ -3751,7 +3816,7 @@ static void dsi_exit(void) } /* DSI1 HW IP initialisation */ -static int omap_dsi1hw_probe(struct platform_device *pdev) +static int __init omap_dsi1hw_probe(struct platform_device *pdev) { int r; dsi.pdev = pdev; @@ -3771,7 +3836,6 @@ static int omap_dsi1hw_remove(struct platform_device *pdev) } static struct platform_driver omap_dsi1hw_driver = { - .probe = omap_dsi1hw_probe, .remove = omap_dsi1hw_remove, .driver = { .name = "omapdss_dsi1", @@ -3779,9 +3843,9 @@ static struct platform_driver omap_dsi1hw_driver = { }, }; -int dsi_init_platform_driver(void) +int __init dsi_init_platform_driver(void) { - return platform_driver_register(&omap_dsi1hw_driver); + return platform_driver_probe(&omap_dsi1hw_driver, omap_dsi1hw_probe); } void dsi_uninit_platform_driver(void) diff --git a/drivers/video/omap2/dss/dss.c b/drivers/video/omap2/dss/dss.c index c3b48a0fcf35..118d320f1e95 100644 --- a/drivers/video/omap2/dss/dss.c +++ b/drivers/video/omap2/dss/dss.c @@ -75,17 +75,17 @@ static struct { struct dss_clock_info cache_dss_cinfo; struct dispc_clock_info cache_dispc_cinfo; - enum dss_clk_source dsi_clk_source; - enum dss_clk_source dispc_clk_source; - enum dss_clk_source lcd_clk_source[MAX_DSS_LCD_MANAGERS]; + enum omap_dss_clk_source dsi_clk_source; + enum omap_dss_clk_source dispc_clk_source; + enum omap_dss_clk_source lcd_clk_source[MAX_DSS_LCD_MANAGERS]; u32 ctx[DSS_SZ_REGS / sizeof(u32)]; } dss; static const char * const dss_generic_clk_source_names[] = { - [DSS_CLK_SRC_DSI_PLL_HSDIV_DISPC] = "DSI_PLL_HSDIV_DISPC", - [DSS_CLK_SRC_DSI_PLL_HSDIV_DSI] = "DSI_PLL_HSDIV_DSI", - [DSS_CLK_SRC_FCK] = "DSS_FCK", + [OMAP_DSS_CLK_SRC_DSI_PLL_HSDIV_DISPC] = "DSI_PLL_HSDIV_DISPC", + [OMAP_DSS_CLK_SRC_DSI_PLL_HSDIV_DSI] = "DSI_PLL_HSDIV_DSI", + [OMAP_DSS_CLK_SRC_FCK] = "DSS_FCK", }; static void dss_clk_enable_all_no_ctx(void); @@ -230,7 +230,7 @@ void dss_sdi_disable(void) REG_FLD_MOD(DSS_PLL_CONTROL, 0, 18, 18); /* SDI_PLL_SYSRESET */ } -const char *dss_get_generic_clk_source_name(enum dss_clk_source clk_src) +const char *dss_get_generic_clk_source_name(enum omap_dss_clk_source clk_src) { return dss_generic_clk_source_names[clk_src]; } @@ -246,8 +246,8 @@ void dss_dump_clocks(struct seq_file *s) seq_printf(s, "- DSS -\n"); - fclk_name = dss_get_generic_clk_source_name(DSS_CLK_SRC_FCK); - fclk_real_name = dss_feat_get_clk_source_name(DSS_CLK_SRC_FCK); + fclk_name = dss_get_generic_clk_source_name(OMAP_DSS_CLK_SRC_FCK); + fclk_real_name = dss_feat_get_clk_source_name(OMAP_DSS_CLK_SRC_FCK); fclk_rate = dss_clk_get_rate(DSS_CLK_FCK); if (dss.dpll4_m4_ck) { @@ -300,16 +300,16 @@ void dss_dump_regs(struct seq_file *s) #undef DUMPREG } -void dss_select_dispc_clk_source(enum dss_clk_source clk_src) +void dss_select_dispc_clk_source(enum omap_dss_clk_source clk_src) { int b; u8 start, end; switch (clk_src) { - case DSS_CLK_SRC_FCK: + case OMAP_DSS_CLK_SRC_FCK: b = 0; break; - case DSS_CLK_SRC_DSI_PLL_HSDIV_DISPC: + case OMAP_DSS_CLK_SRC_DSI_PLL_HSDIV_DISPC: b = 1; dsi_wait_pll_hsdiv_dispc_active(); break; @@ -324,15 +324,15 @@ void dss_select_dispc_clk_source(enum dss_clk_source clk_src) dss.dispc_clk_source = clk_src; } -void dss_select_dsi_clk_source(enum dss_clk_source clk_src) +void dss_select_dsi_clk_source(enum omap_dss_clk_source clk_src) { int b; switch (clk_src) { - case DSS_CLK_SRC_FCK: + case OMAP_DSS_CLK_SRC_FCK: b = 0; break; - case DSS_CLK_SRC_DSI_PLL_HSDIV_DSI: + case OMAP_DSS_CLK_SRC_DSI_PLL_HSDIV_DSI: b = 1; dsi_wait_pll_hsdiv_dsi_active(); break; @@ -346,7 +346,7 @@ void dss_select_dsi_clk_source(enum dss_clk_source clk_src) } void dss_select_lcd_clk_source(enum omap_channel channel, - enum dss_clk_source clk_src) + enum omap_dss_clk_source clk_src) { int b, ix, pos; @@ -354,10 +354,10 @@ void dss_select_lcd_clk_source(enum omap_channel channel, return; switch (clk_src) { - case DSS_CLK_SRC_FCK: + case OMAP_DSS_CLK_SRC_FCK: b = 0; break; - case DSS_CLK_SRC_DSI_PLL_HSDIV_DISPC: + case OMAP_DSS_CLK_SRC_DSI_PLL_HSDIV_DISPC: BUG_ON(channel != OMAP_DSS_CHANNEL_LCD); b = 1; dsi_wait_pll_hsdiv_dispc_active(); @@ -373,17 +373,17 @@ void dss_select_lcd_clk_source(enum omap_channel channel, dss.lcd_clk_source[ix] = clk_src; } -enum dss_clk_source dss_get_dispc_clk_source(void) +enum omap_dss_clk_source dss_get_dispc_clk_source(void) { return dss.dispc_clk_source; } -enum dss_clk_source dss_get_dsi_clk_source(void) +enum omap_dss_clk_source dss_get_dsi_clk_source(void) { return dss.dsi_clk_source; } -enum dss_clk_source dss_get_lcd_clk_source(enum omap_channel channel) +enum omap_dss_clk_source dss_get_lcd_clk_source(enum omap_channel channel) { if (dss_has_feature(FEAT_LCD_CLK_SRC)) { int ix = channel == OMAP_DSS_CHANNEL_LCD ? 0 : 1; @@ -640,7 +640,7 @@ void dss_select_hdmi_venc_clk_source(enum dss_hdmi_venc_clk_source_select hdmi) REG_FLD_MOD(DSS_CONTROL, hdmi, 15, 15); /* VENC_HDMI_SWITCH */ } -static int dss_init(void) +static int __init dss_init(void) { int r; u32 rev; @@ -665,13 +665,18 @@ static int dss_init(void) * the kernel resets it */ omap_writel(omap_readl(0x48050440) & ~0x3, 0x48050440); +#ifdef CONFIG_OMAP2_DSS_SLEEP_BEFORE_RESET /* We need to wait here a bit, otherwise we sometimes start to * get synclost errors, and after that only power cycle will * restore DSS functionality. I have no idea why this happens. * And we have to wait _before_ resetting the DSS, but after * enabling clocks. + * + * This bug was at least present on OMAP3430. It's unknown + * if it happens on OMAP2 or OMAP3630. */ msleep(50); +#endif _omap_dss_reset(); @@ -706,10 +711,10 @@ static int dss_init(void) dss.dpll4_m4_ck = dpll4_m4_ck; - dss.dsi_clk_source = DSS_CLK_SRC_FCK; - dss.dispc_clk_source = DSS_CLK_SRC_FCK; - dss.lcd_clk_source[0] = DSS_CLK_SRC_FCK; - dss.lcd_clk_source[1] = DSS_CLK_SRC_FCK; + dss.dsi_clk_source = OMAP_DSS_CLK_SRC_FCK; + dss.dispc_clk_source = OMAP_DSS_CLK_SRC_FCK; + dss.lcd_clk_source[0] = OMAP_DSS_CLK_SRC_FCK; + dss.lcd_clk_source[1] = OMAP_DSS_CLK_SRC_FCK; dss_save_context(); @@ -1021,6 +1026,14 @@ static void core_dump_clocks(struct seq_file *s) dss.dss_video_fck }; + const char *names[5] = { + "ick", + "fck", + "sys_clk", + "tv_fck", + "video_fck" + }; + seq_printf(s, "- CORE -\n"); seq_printf(s, "internal clk count\t\t%u\n", dss.num_clks_enabled); @@ -1028,8 +1041,11 @@ static void core_dump_clocks(struct seq_file *s) for (i = 0; i < 5; i++) { if (!clocks[i]) continue; - seq_printf(s, "%-15s\t%lu\t%d\n", + seq_printf(s, "%s (%s)%*s\t%lu\t%d\n", + names[i], clocks[i]->name, + 24 - strlen(names[i]) - strlen(clocks[i]->name), + "", clk_get_rate(clocks[i]), clocks[i]->usecount); } @@ -1051,7 +1067,7 @@ void dss_debug_dump_clocks(struct seq_file *s) /* DSS HW IP initialisation */ -static int omap_dsshw_probe(struct platform_device *pdev) +static int __init omap_dsshw_probe(struct platform_device *pdev) { int r; @@ -1115,7 +1131,6 @@ static int omap_dsshw_remove(struct platform_device *pdev) } static struct platform_driver omap_dsshw_driver = { - .probe = omap_dsshw_probe, .remove = omap_dsshw_remove, .driver = { .name = "omapdss_dss", @@ -1123,9 +1138,9 @@ static struct platform_driver omap_dsshw_driver = { }, }; -int dss_init_platform_driver(void) +int __init dss_init_platform_driver(void) { - return platform_driver_register(&omap_dsshw_driver); + return platform_driver_probe(&omap_dsshw_driver, omap_dsshw_probe); } void dss_uninit_platform_driver(void) diff --git a/drivers/video/omap2/dss/dss.h b/drivers/video/omap2/dss/dss.h index c2f582bb19c0..d3b5697134e1 100644 --- a/drivers/video/omap2/dss/dss.h +++ b/drivers/video/omap2/dss/dss.h @@ -117,15 +117,6 @@ enum dss_clock { DSS_CLK_VIDFCK = 1 << 4, /* DSS_96M_FCLK*/ }; -enum dss_clk_source { - DSS_CLK_SRC_DSI_PLL_HSDIV_DISPC, /* OMAP3: DSI1_PLL_FCLK - * OMAP4: PLL1_CLK1 */ - DSS_CLK_SRC_DSI_PLL_HSDIV_DSI, /* OMAP3: DSI2_PLL_FCLK - * OMAP4: PLL1_CLK2 */ - DSS_CLK_SRC_FCK, /* OMAP2/3: DSS1_ALWON_FCLK - * OMAP4: DSS_FCLK */ -}; - enum dss_hdmi_venc_clk_source_select { DSS_VENC_TV_CLK = 0, DSS_HDMI_M_PCLK = 1, @@ -236,7 +227,7 @@ void dss_clk_enable(enum dss_clock clks); void dss_clk_disable(enum dss_clock clks); unsigned long dss_clk_get_rate(enum dss_clock clk); int dss_need_ctx_restore(void); -const char *dss_get_generic_clk_source_name(enum dss_clk_source clk_src); +const char *dss_get_generic_clk_source_name(enum omap_dss_clk_source clk_src); void dss_dump_clocks(struct seq_file *s); void dss_dump_regs(struct seq_file *s); @@ -248,13 +239,13 @@ void dss_sdi_init(u8 datapairs); int dss_sdi_enable(void); void dss_sdi_disable(void); -void dss_select_dispc_clk_source(enum dss_clk_source clk_src); -void dss_select_dsi_clk_source(enum dss_clk_source clk_src); +void dss_select_dispc_clk_source(enum omap_dss_clk_source clk_src); +void dss_select_dsi_clk_source(enum omap_dss_clk_source clk_src); void dss_select_lcd_clk_source(enum omap_channel channel, - enum dss_clk_source clk_src); -enum dss_clk_source dss_get_dispc_clk_source(void); -enum dss_clk_source dss_get_dsi_clk_source(void); -enum dss_clk_source dss_get_lcd_clk_source(enum omap_channel channel); + enum omap_dss_clk_source clk_src); +enum omap_dss_clk_source dss_get_dispc_clk_source(void); +enum omap_dss_clk_source dss_get_dsi_clk_source(void); +enum omap_dss_clk_source dss_get_lcd_clk_source(enum omap_channel channel); void dss_set_venc_output(enum omap_dss_venc_type type); void dss_set_dac_pwrdn_bgz(bool enable); diff --git a/drivers/video/omap2/dss/dss_features.c b/drivers/video/omap2/dss/dss_features.c index 8c50e18bc0b0..6a1b130504e1 100644 --- a/drivers/video/omap2/dss/dss_features.c +++ b/drivers/video/omap2/dss/dss_features.c @@ -178,21 +178,21 @@ static const enum omap_color_mode omap3_dss_supported_color_modes[] = { }; static const char * const omap2_dss_clk_source_names[] = { - [DSS_CLK_SRC_DSI_PLL_HSDIV_DISPC] = "N/A", - [DSS_CLK_SRC_DSI_PLL_HSDIV_DSI] = "N/A", - [DSS_CLK_SRC_FCK] = "DSS_FCLK1", + [OMAP_DSS_CLK_SRC_DSI_PLL_HSDIV_DISPC] = "N/A", + [OMAP_DSS_CLK_SRC_DSI_PLL_HSDIV_DSI] = "N/A", + [OMAP_DSS_CLK_SRC_FCK] = "DSS_FCLK1", }; static const char * const omap3_dss_clk_source_names[] = { - [DSS_CLK_SRC_DSI_PLL_HSDIV_DISPC] = "DSI1_PLL_FCLK", - [DSS_CLK_SRC_DSI_PLL_HSDIV_DSI] = "DSI2_PLL_FCLK", - [DSS_CLK_SRC_FCK] = "DSS1_ALWON_FCLK", + [OMAP_DSS_CLK_SRC_DSI_PLL_HSDIV_DISPC] = "DSI1_PLL_FCLK", + [OMAP_DSS_CLK_SRC_DSI_PLL_HSDIV_DSI] = "DSI2_PLL_FCLK", + [OMAP_DSS_CLK_SRC_FCK] = "DSS1_ALWON_FCLK", }; static const char * const omap4_dss_clk_source_names[] = { - [DSS_CLK_SRC_DSI_PLL_HSDIV_DISPC] = "PLL1_CLK1", - [DSS_CLK_SRC_DSI_PLL_HSDIV_DSI] = "PLL1_CLK2", - [DSS_CLK_SRC_FCK] = "DSS_FCLK", + [OMAP_DSS_CLK_SRC_DSI_PLL_HSDIV_DISPC] = "PLL1_CLK1", + [OMAP_DSS_CLK_SRC_DSI_PLL_HSDIV_DSI] = "PLL1_CLK2", + [OMAP_DSS_CLK_SRC_FCK] = "DSS_FCLK", }; static const struct dss_param_range omap2_dss_param_range[] = { @@ -252,7 +252,8 @@ static struct omap_dss_features omap3430_dss_features = { FEAT_GLOBAL_ALPHA | FEAT_LCDENABLEPOL | FEAT_LCDENABLESIGNAL | FEAT_PCKFREEENABLE | FEAT_FUNCGATED | FEAT_ROWREPEATENABLE | - FEAT_LINEBUFFERSPLIT | FEAT_RESIZECONF, + FEAT_LINEBUFFERSPLIT | FEAT_RESIZECONF | + FEAT_DSI_PLL_FREQSEL | FEAT_DSI_LDO_STATUS, .num_mgrs = 2, .num_ovls = 3, @@ -271,7 +272,8 @@ static struct omap_dss_features omap3630_dss_features = { FEAT_LCDENABLESIGNAL | FEAT_PCKFREEENABLE | FEAT_PRE_MULT_ALPHA | FEAT_FUNCGATED | FEAT_ROWREPEATENABLE | FEAT_LINEBUFFERSPLIT | - FEAT_RESIZECONF | FEAT_DSI_PLL_PWR_BUG, + FEAT_RESIZECONF | FEAT_DSI_PLL_PWR_BUG | + FEAT_DSI_PLL_FREQSEL |FEAT_DSI_LDO_STATUS, .num_mgrs = 2, .num_ovls = 3, @@ -289,7 +291,8 @@ static struct omap_dss_features omap4_dss_features = { .has_feature = FEAT_GLOBAL_ALPHA | FEAT_PRE_MULT_ALPHA | FEAT_MGR_LCD2 | FEAT_GLOBAL_ALPHA_VID1 | - FEAT_CORE_CLK_DIV | FEAT_LCD_CLK_SRC, + FEAT_CORE_CLK_DIV | FEAT_LCD_CLK_SRC | + FEAT_DSI_DCS_CMD_CONFIG_VC | FEAT_DSI_VC_OCP_WIDTH, .num_mgrs = 3, .num_ovls = 3, @@ -337,7 +340,7 @@ bool dss_feat_color_mode_supported(enum omap_plane plane, color_mode; } -const char *dss_feat_get_clk_source_name(enum dss_clk_source id) +const char *dss_feat_get_clk_source_name(enum omap_dss_clk_source id) { return omap_current_dss_features->clksrc_names[id]; } @@ -357,7 +360,7 @@ void dss_feat_get_reg_field(enum dss_feat_reg_field id, u8 *start, u8 *end) *end = omap_current_dss_features->reg_fields[id].end; } -void dss_features_init(void) +void __init dss_features_init(void) { if (cpu_is_omap24xx()) omap_current_dss_features = &omap2_dss_features; diff --git a/drivers/video/omap2/dss/dss_features.h b/drivers/video/omap2/dss/dss_features.h index 37922ce6b8b1..d03f558d181b 100644 --- a/drivers/video/omap2/dss/dss_features.h +++ b/drivers/video/omap2/dss/dss_features.h @@ -26,22 +26,26 @@ /* DSS has feature id */ enum dss_feat_id { - FEAT_GLOBAL_ALPHA = 1 << 0, - FEAT_GLOBAL_ALPHA_VID1 = 1 << 1, - FEAT_PRE_MULT_ALPHA = 1 << 2, - FEAT_LCDENABLEPOL = 1 << 3, - FEAT_LCDENABLESIGNAL = 1 << 4, - FEAT_PCKFREEENABLE = 1 << 5, - FEAT_FUNCGATED = 1 << 6, - FEAT_MGR_LCD2 = 1 << 7, - FEAT_LINEBUFFERSPLIT = 1 << 8, - FEAT_ROWREPEATENABLE = 1 << 9, - FEAT_RESIZECONF = 1 << 10, + FEAT_GLOBAL_ALPHA = 1 << 0, + FEAT_GLOBAL_ALPHA_VID1 = 1 << 1, + FEAT_PRE_MULT_ALPHA = 1 << 2, + FEAT_LCDENABLEPOL = 1 << 3, + FEAT_LCDENABLESIGNAL = 1 << 4, + FEAT_PCKFREEENABLE = 1 << 5, + FEAT_FUNCGATED = 1 << 6, + FEAT_MGR_LCD2 = 1 << 7, + FEAT_LINEBUFFERSPLIT = 1 << 8, + FEAT_ROWREPEATENABLE = 1 << 9, + FEAT_RESIZECONF = 1 << 10, /* Independent core clk divider */ - FEAT_CORE_CLK_DIV = 1 << 11, - FEAT_LCD_CLK_SRC = 1 << 12, + FEAT_CORE_CLK_DIV = 1 << 11, + FEAT_LCD_CLK_SRC = 1 << 12, /* DSI-PLL power command 0x3 is not working */ - FEAT_DSI_PLL_PWR_BUG = 1 << 13, + FEAT_DSI_PLL_PWR_BUG = 1 << 13, + FEAT_DSI_PLL_FREQSEL = 1 << 14, + FEAT_DSI_LDO_STATUS = 1 << 15, + FEAT_DSI_DCS_CMD_CONFIG_VC = 1 << 16, + FEAT_DSI_VC_OCP_WIDTH = 1 << 17, }; /* DSS register field id */ @@ -79,7 +83,7 @@ enum omap_display_type dss_feat_get_supported_displays(enum omap_channel channel enum omap_color_mode dss_feat_get_supported_color_modes(enum omap_plane plane); bool dss_feat_color_mode_supported(enum omap_plane plane, enum omap_color_mode color_mode); -const char *dss_feat_get_clk_source_name(enum dss_clk_source id); +const char *dss_feat_get_clk_source_name(enum omap_dss_clk_source id); bool dss_has_feature(enum dss_feat_id id); void dss_feat_get_reg_field(enum dss_feat_reg_field id, u8 *start, u8 *end); diff --git a/drivers/video/omap2/dss/hdmi.c b/drivers/video/omap2/dss/hdmi.c index a981def8099a..e42a503b6d5b 100644 --- a/drivers/video/omap2/dss/hdmi.c +++ b/drivers/video/omap2/dss/hdmi.c @@ -1052,25 +1052,26 @@ static void update_hdmi_timings(struct hdmi_config *cfg, cfg->timings.hsync_pol = cea_vesa_timings[code].hsync_pol; } -static void hdmi_compute_pll(unsigned long clkin, int phy, - int n, struct hdmi_pll_info *pi) +static void hdmi_compute_pll(struct omap_dss_device *dssdev, int phy, + struct hdmi_pll_info *pi) { - unsigned long refclk; + unsigned long clkin, refclk; u32 mf; + clkin = dss_clk_get_rate(DSS_CLK_SYSCK) / 10000; /* * Input clock is predivided by N + 1 * out put of which is reference clk */ - refclk = clkin / (n + 1); - pi->regn = n; + pi->regn = dssdev->clocks.hdmi.regn; + refclk = clkin / (pi->regn + 1); /* * multiplier is pixel_clk/ref_clk * Multiplying by 100 to avoid fractional part removal */ - pi->regm = (phy * 100/(refclk))/100; - pi->regm2 = 1; + pi->regm = (phy * 100 / (refclk)) / 100; + pi->regm2 = dssdev->clocks.hdmi.regm2; /* * fractional multiplier is remainder of the difference between @@ -1078,14 +1079,14 @@ static void hdmi_compute_pll(unsigned long clkin, int phy, * multiplied by 2^18(262144) divided by the reference clock */ mf = (phy - pi->regm * refclk) * 262144; - pi->regmf = mf/(refclk); + pi->regmf = mf / (refclk); /* * Dcofreq should be set to 1 if required pixel clock * is greater than 1000MHz */ pi->dcofreq = phy > 1000 * 100; - pi->regsd = ((pi->regm * clkin / 10) / ((n + 1) * 250) + 5) / 10; + pi->regsd = ((pi->regm * clkin / 10) / ((pi->regn + 1) * 250) + 5) / 10; DSSDBG("M = %d Mf = %d\n", pi->regm, pi->regmf); DSSDBG("range = %d sd = %d\n", pi->dcofreq, pi->regsd); @@ -1106,7 +1107,7 @@ static int hdmi_power_on(struct omap_dss_device *dssdev) int r, code = 0; struct hdmi_pll_info pll_data; struct omap_video_timings *p; - int clkin, n, phy; + unsigned long phy; hdmi_enable_clocks(1); @@ -1126,11 +1127,9 @@ static int hdmi_power_on(struct omap_dss_device *dssdev) dssdev->panel.timings = cea_vesa_timings[code].timings; update_hdmi_timings(&hdmi.cfg, p, code); - clkin = 3840; /* 38.4 MHz */ - n = 15; /* this is a constant for our math */ phy = p->pixel_clock; - hdmi_compute_pll(clkin, phy, n, &pll_data); + hdmi_compute_pll(dssdev, phy, &pll_data); hdmi_wp_video_start(0); @@ -1160,7 +1159,7 @@ static int hdmi_power_on(struct omap_dss_device *dssdev) * dynamically by user. This can be moved to single location , say * Boardfile. */ - dss_select_dispc_clk_source(DSS_CLK_SRC_FCK); + dss_select_dispc_clk_source(dssdev->clocks.dispc.dispc_fclk_src); /* bypass TV gamma table */ dispc_enable_gamma_table(0); @@ -1276,7 +1275,7 @@ void omapdss_hdmi_display_disable(struct omap_dss_device *dssdev) } /* HDMI HW IP initialisation */ -static int omapdss_hdmihw_probe(struct platform_device *pdev) +static int __init omapdss_hdmihw_probe(struct platform_device *pdev) { struct resource *hdmi_mem; @@ -1313,7 +1312,6 @@ static int omapdss_hdmihw_remove(struct platform_device *pdev) } static struct platform_driver omapdss_hdmihw_driver = { - .probe = omapdss_hdmihw_probe, .remove = omapdss_hdmihw_remove, .driver = { .name = "omapdss_hdmi", @@ -1321,9 +1319,10 @@ static struct platform_driver omapdss_hdmihw_driver = { }, }; -int hdmi_init_platform_driver(void) +int __init hdmi_init_platform_driver(void) { - return platform_driver_register(&omapdss_hdmihw_driver); + return platform_driver_probe(&omapdss_hdmihw_driver, + omapdss_hdmihw_probe); } void hdmi_uninit_platform_driver(void) diff --git a/drivers/video/omap2/dss/manager.c b/drivers/video/omap2/dss/manager.c index bcd37ec86952..08152a706357 100644 --- a/drivers/video/omap2/dss/manager.c +++ b/drivers/video/omap2/dss/manager.c @@ -1475,7 +1475,7 @@ static void omap_dss_add_overlay_manager(struct omap_overlay_manager *manager) list_add_tail(&manager->list, &manager_list); } -int dss_init_overlay_managers(struct platform_device *pdev) +int __init dss_init_overlay_managers(struct platform_device *pdev) { int i, r; diff --git a/drivers/video/omap2/dss/overlay.c b/drivers/video/omap2/dss/overlay.c index f1aca6d04011..46e17c3ff84a 100644 --- a/drivers/video/omap2/dss/overlay.c +++ b/drivers/video/omap2/dss/overlay.c @@ -201,12 +201,16 @@ static ssize_t overlay_enabled_show(struct omap_overlay *ovl, char *buf) static ssize_t overlay_enabled_store(struct omap_overlay *ovl, const char *buf, size_t size) { - int r; + int r, enable; struct omap_overlay_info info; ovl->get_overlay_info(ovl, &info); - info.enabled = simple_strtoul(buf, NULL, 10); + r = kstrtoint(buf, 0, &enable); + if (r) + return r; + + info.enabled = !!enable; r = ovl->set_overlay_info(ovl, &info); if (r) @@ -231,8 +235,13 @@ static ssize_t overlay_global_alpha_store(struct omap_overlay *ovl, const char *buf, size_t size) { int r; + u8 alpha; struct omap_overlay_info info; + r = kstrtou8(buf, 0, &alpha); + if (r) + return r; + ovl->get_overlay_info(ovl, &info); /* Video1 plane does not support global alpha @@ -242,7 +251,7 @@ static ssize_t overlay_global_alpha_store(struct omap_overlay *ovl, ovl->id == OMAP_DSS_VIDEO1) info.global_alpha = 255; else - info.global_alpha = simple_strtoul(buf, NULL, 10); + info.global_alpha = alpha; r = ovl->set_overlay_info(ovl, &info); if (r) @@ -268,8 +277,13 @@ static ssize_t overlay_pre_mult_alpha_store(struct omap_overlay *ovl, const char *buf, size_t size) { int r; + u8 alpha; struct omap_overlay_info info; + r = kstrtou8(buf, 0, &alpha); + if (r) + return r; + ovl->get_overlay_info(ovl, &info); /* only GFX and Video2 plane support pre alpha multiplied @@ -279,7 +293,7 @@ static ssize_t overlay_pre_mult_alpha_store(struct omap_overlay *ovl, ovl->id == OMAP_DSS_VIDEO1) info.pre_mult_alpha = 0; else - info.pre_mult_alpha = simple_strtoul(buf, NULL, 10); + info.pre_mult_alpha = alpha; r = ovl->set_overlay_info(ovl, &info); if (r) @@ -491,13 +505,18 @@ static int omap_dss_set_manager(struct omap_overlay *ovl, ovl->manager = mgr; dss_clk_enable(DSS_CLK_ICK | DSS_CLK_FCK); - /* XXX: on manual update display, in auto update mode, a bug happens - * here. When an overlay is first enabled on LCD, then it's disabled, - * and the manager is changed to TV, we sometimes get SYNC_LOST_DIGIT - * errors. Waiting before changing the channel_out fixes it. I'm - * guessing that the overlay is still somehow being used for the LCD, - * but I don't understand how or why. */ - msleep(40); + /* XXX: When there is an overlay on a DSI manual update display, and + * the overlay is first disabled, then moved to tv, and enabled, we + * seem to get SYNC_LOST_DIGIT error. + * + * Waiting doesn't seem to help, but updating the manual update display + * after disabling the overlay seems to fix this. This hints that the + * overlay is perhaps somehow tied to the LCD output until the output + * is updated. + * + * Userspace workaround for this is to update the LCD after disabling + * the overlay, but before moving the overlay to TV. + */ dispc_set_channel_out(ovl->id, mgr->id); dss_clk_disable(DSS_CLK_ICK | DSS_CLK_FCK); @@ -570,7 +589,7 @@ void dss_overlay_setup_l4_manager(struct omap_overlay_manager *mgr) } #endif -void dss_init_overlays(struct platform_device *pdev) +void __init dss_init_overlays(struct platform_device *pdev) { int i, r; diff --git a/drivers/video/omap2/dss/rfbi.c b/drivers/video/omap2/dss/rfbi.c index 5ea17f49c611..8bbe83e16970 100644 --- a/drivers/video/omap2/dss/rfbi.c +++ b/drivers/video/omap2/dss/rfbi.c @@ -1013,7 +1013,7 @@ int rfbi_init_display(struct omap_dss_device *dssdev) } /* RFBI HW IP initialisation */ -static int omap_rfbihw_probe(struct platform_device *pdev) +static int __init omap_rfbihw_probe(struct platform_device *pdev) { u32 rev; u32 l; @@ -1065,7 +1065,6 @@ static int omap_rfbihw_remove(struct platform_device *pdev) } static struct platform_driver omap_rfbihw_driver = { - .probe = omap_rfbihw_probe, .remove = omap_rfbihw_remove, .driver = { .name = "omapdss_rfbi", @@ -1073,9 +1072,9 @@ static struct platform_driver omap_rfbihw_driver = { }, }; -int rfbi_init_platform_driver(void) +int __init rfbi_init_platform_driver(void) { - return platform_driver_register(&omap_rfbihw_driver); + return platform_driver_probe(&omap_rfbihw_driver, omap_rfbihw_probe); } void rfbi_uninit_platform_driver(void) diff --git a/drivers/video/omap2/dss/sdi.c b/drivers/video/omap2/dss/sdi.c index 54a53e648180..87d5a7ef69f0 100644 --- a/drivers/video/omap2/dss/sdi.c +++ b/drivers/video/omap2/dss/sdi.c @@ -160,7 +160,7 @@ int sdi_init_display(struct omap_dss_device *dssdev) return 0; } -int sdi_init(void) +int __init sdi_init(void) { return 0; } diff --git a/drivers/video/omap2/dss/venc.c b/drivers/video/omap2/dss/venc.c index 8e35a5bae429..e55cefeb0bb7 100644 --- a/drivers/video/omap2/dss/venc.c +++ b/drivers/video/omap2/dss/venc.c @@ -373,8 +373,11 @@ static void venc_reset(void) } } +#ifdef CONFIG_OMAP2_DSS_SLEEP_AFTER_VENC_RESET /* the magical sleep that makes things work */ + /* XXX more info? What bug this circumvents? */ msleep(20); +#endif } static void venc_enable_clocks(int enable) @@ -473,6 +476,12 @@ static int venc_panel_enable(struct omap_dss_device *dssdev) mutex_lock(&venc.venc_lock); + r = omap_dss_start_device(dssdev); + if (r) { + DSSERR("failed to start device\n"); + goto err0; + } + if (dssdev->state != OMAP_DSS_DISPLAY_DISABLED) { r = -EINVAL; goto err1; @@ -484,10 +493,11 @@ static int venc_panel_enable(struct omap_dss_device *dssdev) dssdev->state = OMAP_DSS_DISPLAY_ACTIVE; - /* wait couple of vsyncs until enabling the LCD */ - msleep(50); - + mutex_unlock(&venc.venc_lock); + return 0; err1: + omap_dss_stop_device(dssdev); +err0: mutex_unlock(&venc.venc_lock); return r; @@ -510,10 +520,9 @@ static void venc_panel_disable(struct omap_dss_device *dssdev) venc_power_off(dssdev); - /* wait at least 5 vsyncs after disabling the LCD */ - msleep(100); - dssdev->state = OMAP_DSS_DISPLAY_DISABLED; + + omap_dss_stop_device(dssdev); end: mutex_unlock(&venc.venc_lock); } @@ -714,7 +723,7 @@ void venc_dump_regs(struct seq_file *s) } /* VENC HW IP initialisation */ -static int omap_venchw_probe(struct platform_device *pdev) +static int __init omap_venchw_probe(struct platform_device *pdev) { u8 rev_id; struct resource *venc_mem; @@ -759,7 +768,6 @@ static int omap_venchw_remove(struct platform_device *pdev) } static struct platform_driver omap_venchw_driver = { - .probe = omap_venchw_probe, .remove = omap_venchw_remove, .driver = { .name = "omapdss_venc", @@ -767,12 +775,12 @@ static struct platform_driver omap_venchw_driver = { }, }; -int venc_init_platform_driver(void) +int __init venc_init_platform_driver(void) { if (cpu_is_omap44xx()) return 0; - return platform_driver_register(&omap_venchw_driver); + return platform_driver_probe(&omap_venchw_driver, omap_venchw_probe); } void venc_uninit_platform_driver(void) diff --git a/drivers/video/omap2/omapfb/omapfb-ioctl.c b/drivers/video/omap2/omapfb/omapfb-ioctl.c index 6f435450987e..b4636b168d86 100644 --- a/drivers/video/omap2/omapfb/omapfb-ioctl.c +++ b/drivers/video/omap2/omapfb/omapfb-ioctl.c @@ -895,8 +895,16 @@ int omapfb_ioctl(struct fb_info *fbi, unsigned int cmd, unsigned long arg) p.display_info.xres = xres; p.display_info.yres = yres; - p.display_info.width = 0; - p.display_info.height = 0; + + if (display->driver->get_dimensions) { + u32 w, h; + display->driver->get_dimensions(display, &w, &h); + p.display_info.width = w; + p.display_info.height = h; + } else { + p.display_info.width = 0; + p.display_info.height = 0; + } if (copy_to_user((void __user *)arg, &p.display_info, sizeof(p.display_info))) diff --git a/drivers/video/omap2/omapfb/omapfb-main.c b/drivers/video/omap2/omapfb/omapfb-main.c index 505ec6672049..1f9cb3a673a3 100644 --- a/drivers/video/omap2/omapfb/omapfb-main.c +++ b/drivers/video/omap2/omapfb/omapfb-main.c @@ -702,8 +702,16 @@ int check_fb_var(struct fb_info *fbi, struct fb_var_screeninfo *var) var->xres, var->yres, var->xres_virtual, var->yres_virtual); - var->height = -1; - var->width = -1; + if (display && display->driver->get_dimensions) { + u32 w, h; + display->driver->get_dimensions(display, &w, &h); + var->width = DIV_ROUND_CLOSEST(w, 1000); + var->height = DIV_ROUND_CLOSEST(h, 1000); + } else { + var->height = -1; + var->width = -1; + } + var->grayscale = 0; if (display && display->driver->get_timings) { @@ -1263,7 +1271,6 @@ static int omapfb_blank(int blank, struct fb_info *fbi) struct omapfb_info *ofbi = FB2OFB(fbi); struct omapfb2_device *fbdev = ofbi->fbdev; struct omap_dss_device *display = fb2display(fbi); - int do_update = 0; int r = 0; if (!display) @@ -1279,11 +1286,6 @@ static int omapfb_blank(int blank, struct fb_info *fbi) if (display->driver->resume) r = display->driver->resume(display); - if (r == 0 && display->driver->get_update_mode && - display->driver->get_update_mode(display) == - OMAP_DSS_UPDATE_MANUAL) - do_update = 1; - break; case FB_BLANK_NORMAL: @@ -1307,13 +1309,6 @@ static int omapfb_blank(int blank, struct fb_info *fbi) exit: omapfb_unlock(fbdev); - if (r == 0 && do_update && display->driver->update) { - u16 w, h; - display->driver->get_resolution(display, &w, &h); - - r = display->driver->update(display, 0, 0, w, h); - } - return r; } @@ -2185,6 +2180,61 @@ static int omapfb_parse_def_modes(struct omapfb2_device *fbdev) return r; } +static int omapfb_init_display(struct omapfb2_device *fbdev, + struct omap_dss_device *dssdev) +{ + struct omap_dss_driver *dssdrv = dssdev->driver; + int r; + + r = dssdrv->enable(dssdev); + if (r) { + dev_warn(fbdev->dev, "Failed to enable display '%s'\n", + dssdev->name); + return r; + } + + if (dssdev->caps & OMAP_DSS_DISPLAY_CAP_MANUAL_UPDATE) { + u16 w, h; + if (dssdrv->enable_te) { + r = dssdrv->enable_te(dssdev, 1); + if (r) { + dev_err(fbdev->dev, "Failed to set TE\n"); + return r; + } + } + + if (dssdrv->set_update_mode) { + r = dssdrv->set_update_mode(dssdev, + OMAP_DSS_UPDATE_MANUAL); + if (r) { + dev_err(fbdev->dev, + "Failed to set update mode\n"); + return r; + } + } + + dssdrv->get_resolution(dssdev, &w, &h); + r = dssdrv->update(dssdev, 0, 0, w, h); + if (r) { + dev_err(fbdev->dev, + "Failed to update display\n"); + return r; + } + } else { + if (dssdrv->set_update_mode) { + r = dssdrv->set_update_mode(dssdev, + OMAP_DSS_UPDATE_AUTO); + if (r) { + dev_err(fbdev->dev, + "Failed to set update mode\n"); + return r; + } + } + } + + return 0; +} + static int omapfb_probe(struct platform_device *pdev) { struct omapfb2_device *fbdev = NULL; @@ -2284,30 +2334,13 @@ static int omapfb_probe(struct platform_device *pdev) } if (def_display) { - struct omap_dss_driver *dssdrv = def_display->driver; - - r = def_display->driver->enable(def_display); + r = omapfb_init_display(fbdev, def_display); if (r) { - dev_warn(fbdev->dev, "Failed to enable display '%s'\n", - def_display->name); + dev_err(fbdev->dev, + "failed to initialize default " + "display\n"); goto cleanup; } - - if (def_display->caps & OMAP_DSS_DISPLAY_CAP_MANUAL_UPDATE) { - u16 w, h; - if (dssdrv->enable_te) - dssdrv->enable_te(def_display, 1); - if (dssdrv->set_update_mode) - dssdrv->set_update_mode(def_display, - OMAP_DSS_UPDATE_MANUAL); - - dssdrv->get_resolution(def_display, &w, &h); - def_display->driver->update(def_display, 0, 0, w, h); - } else { - if (dssdrv->set_update_mode) - dssdrv->set_update_mode(def_display, - OMAP_DSS_UPDATE_AUTO); - } } DBG("create sysfs for fbs\n"); diff --git a/drivers/video/omap2/omapfb/omapfb-sysfs.c b/drivers/video/omap2/omapfb/omapfb-sysfs.c index 6f9c72cd6bb0..672da5486bf4 100644 --- a/drivers/video/omap2/omapfb/omapfb-sysfs.c +++ b/drivers/video/omap2/omapfb/omapfb-sysfs.c @@ -50,10 +50,12 @@ static ssize_t store_rotate_type(struct device *dev, struct fb_info *fbi = dev_get_drvdata(dev); struct omapfb_info *ofbi = FB2OFB(fbi); struct omapfb2_mem_region *rg; - enum omap_dss_rotation_type rot_type; + int rot_type; int r; - rot_type = simple_strtoul(buf, NULL, 0); + r = kstrtoint(buf, 0, &rot_type); + if (r) + return r; if (rot_type != OMAP_DSS_ROT_DMA && rot_type != OMAP_DSS_ROT_VRFB) return -EINVAL; @@ -102,14 +104,15 @@ static ssize_t store_mirror(struct device *dev, { struct fb_info *fbi = dev_get_drvdata(dev); struct omapfb_info *ofbi = FB2OFB(fbi); - unsigned long mirror; + int mirror; int r; struct fb_var_screeninfo new_var; - mirror = simple_strtoul(buf, NULL, 0); + r = kstrtoint(buf, 0, &mirror); + if (r) + return r; - if (mirror != 0 && mirror != 1) - return -EINVAL; + mirror = !!mirror; if (!lock_fb_info(fbi)) return -ENODEV; @@ -445,7 +448,11 @@ static ssize_t store_size(struct device *dev, struct device_attribute *attr, int r; int i; - size = PAGE_ALIGN(simple_strtoul(buf, NULL, 0)); + r = kstrtoul(buf, 0, &size); + if (r) + return r; + + size = PAGE_ALIGN(size); if (!lock_fb_info(fbi)) return -ENODEV; |