diff options
Diffstat (limited to 'drivers/video/fbdev/omap2/omapfb/dss/core.c')
-rw-r--r-- | drivers/video/fbdev/omap2/omapfb/dss/core.c | 343 |
1 files changed, 343 insertions, 0 deletions
diff --git a/drivers/video/fbdev/omap2/omapfb/dss/core.c b/drivers/video/fbdev/omap2/omapfb/dss/core.c new file mode 100644 index 0000000..5a87179 --- /dev/null +++ b/drivers/video/fbdev/omap2/omapfb/dss/core.c @@ -0,0 +1,343 @@ +/* + * linux/drivers/video/omap2/dss/core.c + * + * Copyright (C) 2009 Nokia Corporation + * Author: Tomi Valkeinen <tomi.valkeinen@nokia.com> + * + * Some code and ideas taken from drivers/video/omap/ driver + * by Imre Deak. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 as published by + * the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License along with + * this program. If not, see <http://www.gnu.org/licenses/>. + */ + +#define DSS_SUBSYS_NAME "CORE" + +#include <linux/kernel.h> +#include <linux/module.h> +#include <linux/clk.h> +#include <linux/err.h> +#include <linux/platform_device.h> +#include <linux/seq_file.h> +#include <linux/debugfs.h> +#include <linux/io.h> +#include <linux/device.h> +#include <linux/regulator/consumer.h> +#include <linux/suspend.h> +#include <linux/slab.h> + +#include <video/omapdss.h> + +#include "dss.h" +#include "dss_features.h" + +static struct { + struct platform_device *pdev; + + const char *default_display_name; +} core; + +static char *def_disp_name; +module_param_named(def_disp, def_disp_name, charp, 0); +MODULE_PARM_DESC(def_disp, "default display name"); + +const char *omapdss_get_default_display_name(void) +{ + return core.default_display_name; +} +EXPORT_SYMBOL(omapdss_get_default_display_name); + +enum omapdss_version omapdss_get_version(void) +{ + struct omap_dss_board_info *pdata = core.pdev->dev.platform_data; + return pdata->version; +} +EXPORT_SYMBOL(omapdss_get_version); + +struct platform_device *dss_get_core_pdev(void) +{ + return core.pdev; +} + +int dss_dsi_enable_pads(int dsi_id, unsigned lane_mask) +{ + struct omap_dss_board_info *board_data = core.pdev->dev.platform_data; + + if (!board_data->dsi_enable_pads) + return -ENOENT; + + return board_data->dsi_enable_pads(dsi_id, lane_mask); +} + +void dss_dsi_disable_pads(int dsi_id, unsigned lane_mask) +{ + struct omap_dss_board_info *board_data = core.pdev->dev.platform_data; + + if (!board_data->dsi_disable_pads) + return; + + return board_data->dsi_disable_pads(dsi_id, lane_mask); +} + +int dss_set_min_bus_tput(struct device *dev, unsigned long tput) +{ + struct omap_dss_board_info *pdata = core.pdev->dev.platform_data; + + if (pdata->set_min_bus_tput) + return pdata->set_min_bus_tput(dev, tput); + else + return 0; +} + +#if defined(CONFIG_FB_OMAP2_DSS_DEBUGFS) +static int dss_debug_show(struct seq_file *s, void *unused) +{ + void (*func)(struct seq_file *) = s->private; + func(s); + return 0; +} + +static int dss_debug_open(struct inode *inode, struct file *file) +{ + return single_open(file, dss_debug_show, inode->i_private); +} + +static const struct file_operations dss_debug_fops = { + .open = dss_debug_open, + .read = seq_read, + .llseek = seq_lseek, + .release = single_release, +}; + +static struct dentry *dss_debugfs_dir; + +static int dss_initialize_debugfs(void) +{ + dss_debugfs_dir = debugfs_create_dir("omapdss", NULL); + if (IS_ERR(dss_debugfs_dir)) { + int err = PTR_ERR(dss_debugfs_dir); + dss_debugfs_dir = NULL; + return err; + } + + debugfs_create_file("clk", S_IRUGO, dss_debugfs_dir, + &dss_debug_dump_clocks, &dss_debug_fops); + + return 0; +} + +static void dss_uninitialize_debugfs(void) +{ + if (dss_debugfs_dir) + debugfs_remove_recursive(dss_debugfs_dir); +} + +int dss_debugfs_create_file(const char *name, void (*write)(struct seq_file *)) +{ + struct dentry *d; + + d = debugfs_create_file(name, S_IRUGO, dss_debugfs_dir, + write, &dss_debug_fops); + + return PTR_ERR_OR_ZERO(d); +} +#else /* CONFIG_FB_OMAP2_DSS_DEBUGFS */ +static inline int dss_initialize_debugfs(void) +{ + return 0; +} +static inline void dss_uninitialize_debugfs(void) +{ +} +int dss_debugfs_create_file(const char *name, void (*write)(struct seq_file *)) +{ + return 0; +} +#endif /* CONFIG_FB_OMAP2_DSS_DEBUGFS */ + +/* PLATFORM DEVICE */ +static int omap_dss_pm_notif(struct notifier_block *b, unsigned long v, void *d) +{ + DSSDBG("pm notif %lu\n", v); + + switch (v) { + case PM_SUSPEND_PREPARE: + case PM_HIBERNATION_PREPARE: + case PM_RESTORE_PREPARE: + DSSDBG("suspending displays\n"); + return dss_suspend_all_devices(); + + case PM_POST_SUSPEND: + case PM_POST_HIBERNATION: + case PM_POST_RESTORE: + DSSDBG("resuming displays\n"); + return dss_resume_all_devices(); + + default: + return 0; + } +} + +static struct notifier_block omap_dss_pm_notif_block = { + .notifier_call = omap_dss_pm_notif, +}; + +static int __init omap_dss_probe(struct platform_device *pdev) +{ + struct omap_dss_board_info *pdata = pdev->dev.platform_data; + int r; + + core.pdev = pdev; + + dss_features_init(omapdss_get_version()); + + r = dss_initialize_debugfs(); + if (r) + goto err_debugfs; + + if (def_disp_name) + core.default_display_name = def_disp_name; + else if (pdata->default_display_name) + core.default_display_name = pdata->default_display_name; + else if (pdata->default_device) + core.default_display_name = pdata->default_device->name; + + register_pm_notifier(&omap_dss_pm_notif_block); + + return 0; + +err_debugfs: + + return r; +} + +static int omap_dss_remove(struct platform_device *pdev) +{ + unregister_pm_notifier(&omap_dss_pm_notif_block); + + dss_uninitialize_debugfs(); + + return 0; +} + +static void omap_dss_shutdown(struct platform_device *pdev) +{ + DSSDBG("shutdown\n"); + dss_disable_all_devices(); +} + +static struct platform_driver omap_dss_driver = { + .remove = omap_dss_remove, + .shutdown = omap_dss_shutdown, + .driver = { + .name = "omapdss", + }, +}; + +/* INIT */ +static int (*dss_output_drv_reg_funcs[])(void) __initdata = { + dss_init_platform_driver, + dispc_init_platform_driver, +#ifdef CONFIG_FB_OMAP2_DSS_DSI + dsi_init_platform_driver, +#endif +#ifdef CONFIG_FB_OMAP2_DSS_DPI + dpi_init_platform_driver, +#endif +#ifdef CONFIG_FB_OMAP2_DSS_SDI + sdi_init_platform_driver, +#endif +#ifdef CONFIG_FB_OMAP2_DSS_RFBI + rfbi_init_platform_driver, +#endif +#ifdef CONFIG_FB_OMAP2_DSS_VENC + venc_init_platform_driver, +#endif +#ifdef CONFIG_FB_OMAP4_DSS_HDMI + hdmi4_init_platform_driver, +#endif +#ifdef CONFIG_FB_OMAP5_DSS_HDMI + hdmi5_init_platform_driver, +#endif +}; + +static void (*dss_output_drv_unreg_funcs[])(void) = { +#ifdef CONFIG_FB_OMAP5_DSS_HDMI + hdmi5_uninit_platform_driver, +#endif +#ifdef CONFIG_FB_OMAP4_DSS_HDMI + hdmi4_uninit_platform_driver, +#endif +#ifdef CONFIG_FB_OMAP2_DSS_VENC + venc_uninit_platform_driver, +#endif +#ifdef CONFIG_FB_OMAP2_DSS_RFBI + rfbi_uninit_platform_driver, +#endif +#ifdef CONFIG_FB_OMAP2_DSS_SDI + sdi_uninit_platform_driver, +#endif +#ifdef CONFIG_FB_OMAP2_DSS_DPI + dpi_uninit_platform_driver, +#endif +#ifdef CONFIG_FB_OMAP2_DSS_DSI + dsi_uninit_platform_driver, +#endif + dispc_uninit_platform_driver, + dss_uninit_platform_driver, +}; + +static int __init omap_dss_init(void) +{ + int r; + int i; + + r = platform_driver_probe(&omap_dss_driver, omap_dss_probe); + if (r) + return r; + + for (i = 0; i < ARRAY_SIZE(dss_output_drv_reg_funcs); ++i) { + r = dss_output_drv_reg_funcs[i](); + if (r) + goto err_reg; + } + + return 0; + +err_reg: + for (i = ARRAY_SIZE(dss_output_drv_reg_funcs) - i; + i < ARRAY_SIZE(dss_output_drv_reg_funcs); + ++i) + dss_output_drv_unreg_funcs[i](); + + platform_driver_unregister(&omap_dss_driver); + + return r; +} + +static void __exit omap_dss_exit(void) +{ + int i; + + for (i = 0; i < ARRAY_SIZE(dss_output_drv_unreg_funcs); ++i) + dss_output_drv_unreg_funcs[i](); + + platform_driver_unregister(&omap_dss_driver); +} + +module_init(omap_dss_init); +module_exit(omap_dss_exit); + +MODULE_AUTHOR("Tomi Valkeinen <tomi.valkeinen@nokia.com>"); +MODULE_DESCRIPTION("OMAP2/3 Display Subsystem"); +MODULE_LICENSE("GPL v2"); + |