at v4.6 327 lines 7.3 kB view raw
1/* 2 * linux/drivers/video/omap2/dss/core.c 3 * 4 * Copyright (C) 2009 Nokia Corporation 5 * Author: Tomi Valkeinen <tomi.valkeinen@nokia.com> 6 * 7 * Some code and ideas taken from drivers/video/omap/ driver 8 * by Imre Deak. 9 * 10 * This program is free software; you can redistribute it and/or modify it 11 * under the terms of the GNU General Public License version 2 as published by 12 * the Free Software Foundation. 13 * 14 * This program is distributed in the hope that it will be useful, but WITHOUT 15 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 16 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for 17 * more details. 18 * 19 * You should have received a copy of the GNU General Public License along with 20 * this program. If not, see <http://www.gnu.org/licenses/>. 21 */ 22 23#define DSS_SUBSYS_NAME "CORE" 24 25#include <linux/kernel.h> 26#include <linux/module.h> 27#include <linux/clk.h> 28#include <linux/err.h> 29#include <linux/platform_device.h> 30#include <linux/seq_file.h> 31#include <linux/debugfs.h> 32#include <linux/io.h> 33#include <linux/device.h> 34#include <linux/regulator/consumer.h> 35#include <linux/suspend.h> 36#include <linux/slab.h> 37 38#include <video/omapdss.h> 39 40#include "dss.h" 41#include "dss_features.h" 42 43static struct { 44 struct platform_device *pdev; 45 46 const char *default_display_name; 47} core; 48 49static char *def_disp_name; 50module_param_named(def_disp, def_disp_name, charp, 0); 51MODULE_PARM_DESC(def_disp, "default display name"); 52 53const char *omapdss_get_default_display_name(void) 54{ 55 return core.default_display_name; 56} 57EXPORT_SYMBOL(omapdss_get_default_display_name); 58 59enum omapdss_version omapdss_get_version(void) 60{ 61 struct omap_dss_board_info *pdata = core.pdev->dev.platform_data; 62 return pdata->version; 63} 64EXPORT_SYMBOL(omapdss_get_version); 65 66struct platform_device *dss_get_core_pdev(void) 67{ 68 return core.pdev; 69} 70 71int dss_dsi_enable_pads(int dsi_id, unsigned lane_mask) 72{ 73 struct omap_dss_board_info *board_data = core.pdev->dev.platform_data; 74 75 if (!board_data->dsi_enable_pads) 76 return -ENOENT; 77 78 return board_data->dsi_enable_pads(dsi_id, lane_mask); 79} 80 81void dss_dsi_disable_pads(int dsi_id, unsigned lane_mask) 82{ 83 struct omap_dss_board_info *board_data = core.pdev->dev.platform_data; 84 85 if (!board_data->dsi_disable_pads) 86 return; 87 88 return board_data->dsi_disable_pads(dsi_id, lane_mask); 89} 90 91int dss_set_min_bus_tput(struct device *dev, unsigned long tput) 92{ 93 struct omap_dss_board_info *pdata = core.pdev->dev.platform_data; 94 95 if (pdata->set_min_bus_tput) 96 return pdata->set_min_bus_tput(dev, tput); 97 else 98 return 0; 99} 100 101#if defined(CONFIG_OMAP2_DSS_DEBUGFS) 102static int dss_debug_show(struct seq_file *s, void *unused) 103{ 104 void (*func)(struct seq_file *) = s->private; 105 func(s); 106 return 0; 107} 108 109static int dss_debug_open(struct inode *inode, struct file *file) 110{ 111 return single_open(file, dss_debug_show, inode->i_private); 112} 113 114static const struct file_operations dss_debug_fops = { 115 .open = dss_debug_open, 116 .read = seq_read, 117 .llseek = seq_lseek, 118 .release = single_release, 119}; 120 121static struct dentry *dss_debugfs_dir; 122 123static int dss_initialize_debugfs(void) 124{ 125 dss_debugfs_dir = debugfs_create_dir("omapdss", NULL); 126 if (IS_ERR(dss_debugfs_dir)) { 127 int err = PTR_ERR(dss_debugfs_dir); 128 dss_debugfs_dir = NULL; 129 return err; 130 } 131 132 debugfs_create_file("clk", S_IRUGO, dss_debugfs_dir, 133 &dss_debug_dump_clocks, &dss_debug_fops); 134 135 return 0; 136} 137 138static void dss_uninitialize_debugfs(void) 139{ 140 if (dss_debugfs_dir) 141 debugfs_remove_recursive(dss_debugfs_dir); 142} 143 144int dss_debugfs_create_file(const char *name, void (*write)(struct seq_file *)) 145{ 146 struct dentry *d; 147 148 d = debugfs_create_file(name, S_IRUGO, dss_debugfs_dir, 149 write, &dss_debug_fops); 150 151 return PTR_ERR_OR_ZERO(d); 152} 153#else /* CONFIG_OMAP2_DSS_DEBUGFS */ 154static inline int dss_initialize_debugfs(void) 155{ 156 return 0; 157} 158static inline void dss_uninitialize_debugfs(void) 159{ 160} 161int dss_debugfs_create_file(const char *name, void (*write)(struct seq_file *)) 162{ 163 return 0; 164} 165#endif /* CONFIG_OMAP2_DSS_DEBUGFS */ 166 167/* PLATFORM DEVICE */ 168 169static void dss_disable_all_devices(void) 170{ 171 struct omap_dss_device *dssdev = NULL; 172 173 for_each_dss_dev(dssdev) { 174 if (!dssdev->driver) 175 continue; 176 177 if (dssdev->state == OMAP_DSS_DISPLAY_ACTIVE) 178 dssdev->driver->disable(dssdev); 179 } 180} 181 182static int __init omap_dss_probe(struct platform_device *pdev) 183{ 184 struct omap_dss_board_info *pdata = pdev->dev.platform_data; 185 int r; 186 187 core.pdev = pdev; 188 189 dss_features_init(omapdss_get_version()); 190 191 r = dss_initialize_debugfs(); 192 if (r) 193 goto err_debugfs; 194 195 if (def_disp_name) 196 core.default_display_name = def_disp_name; 197 else if (pdata->default_display_name) 198 core.default_display_name = pdata->default_display_name; 199 else if (pdata->default_device) 200 core.default_display_name = pdata->default_device->name; 201 202 return 0; 203 204err_debugfs: 205 206 return r; 207} 208 209static int omap_dss_remove(struct platform_device *pdev) 210{ 211 dss_uninitialize_debugfs(); 212 213 return 0; 214} 215 216static void omap_dss_shutdown(struct platform_device *pdev) 217{ 218 DSSDBG("shutdown\n"); 219 dss_disable_all_devices(); 220} 221 222static struct platform_driver omap_dss_driver = { 223 .remove = omap_dss_remove, 224 .shutdown = omap_dss_shutdown, 225 .driver = { 226 .name = "omapdss", 227 }, 228}; 229 230/* INIT */ 231static int (*dss_output_drv_reg_funcs[])(void) __initdata = { 232 dss_init_platform_driver, 233 dispc_init_platform_driver, 234#ifdef CONFIG_OMAP2_DSS_DSI 235 dsi_init_platform_driver, 236#endif 237#ifdef CONFIG_OMAP2_DSS_DPI 238 dpi_init_platform_driver, 239#endif 240#ifdef CONFIG_OMAP2_DSS_SDI 241 sdi_init_platform_driver, 242#endif 243#ifdef CONFIG_OMAP2_DSS_RFBI 244 rfbi_init_platform_driver, 245#endif 246#ifdef CONFIG_OMAP2_DSS_VENC 247 venc_init_platform_driver, 248#endif 249#ifdef CONFIG_OMAP4_DSS_HDMI 250 hdmi4_init_platform_driver, 251#endif 252#ifdef CONFIG_OMAP5_DSS_HDMI 253 hdmi5_init_platform_driver, 254#endif 255}; 256 257static void (*dss_output_drv_unreg_funcs[])(void) = { 258#ifdef CONFIG_OMAP5_DSS_HDMI 259 hdmi5_uninit_platform_driver, 260#endif 261#ifdef CONFIG_OMAP4_DSS_HDMI 262 hdmi4_uninit_platform_driver, 263#endif 264#ifdef CONFIG_OMAP2_DSS_VENC 265 venc_uninit_platform_driver, 266#endif 267#ifdef CONFIG_OMAP2_DSS_RFBI 268 rfbi_uninit_platform_driver, 269#endif 270#ifdef CONFIG_OMAP2_DSS_SDI 271 sdi_uninit_platform_driver, 272#endif 273#ifdef CONFIG_OMAP2_DSS_DPI 274 dpi_uninit_platform_driver, 275#endif 276#ifdef CONFIG_OMAP2_DSS_DSI 277 dsi_uninit_platform_driver, 278#endif 279 dispc_uninit_platform_driver, 280 dss_uninit_platform_driver, 281}; 282 283static int __init omap_dss_init(void) 284{ 285 int r; 286 int i; 287 288 r = platform_driver_probe(&omap_dss_driver, omap_dss_probe); 289 if (r) 290 return r; 291 292 for (i = 0; i < ARRAY_SIZE(dss_output_drv_reg_funcs); ++i) { 293 r = dss_output_drv_reg_funcs[i](); 294 if (r) 295 goto err_reg; 296 } 297 298 return 0; 299 300err_reg: 301 for (i = ARRAY_SIZE(dss_output_drv_reg_funcs) - i; 302 i < ARRAY_SIZE(dss_output_drv_reg_funcs); 303 ++i) 304 dss_output_drv_unreg_funcs[i](); 305 306 platform_driver_unregister(&omap_dss_driver); 307 308 return r; 309} 310 311static void __exit omap_dss_exit(void) 312{ 313 int i; 314 315 for (i = 0; i < ARRAY_SIZE(dss_output_drv_unreg_funcs); ++i) 316 dss_output_drv_unreg_funcs[i](); 317 318 platform_driver_unregister(&omap_dss_driver); 319} 320 321module_init(omap_dss_init); 322module_exit(omap_dss_exit); 323 324MODULE_AUTHOR("Tomi Valkeinen <tomi.valkeinen@nokia.com>"); 325MODULE_DESCRIPTION("OMAP2/3 Display Subsystem"); 326MODULE_LICENSE("GPL v2"); 327