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 36#include <video/omapdss.h> 37 38#include "dss.h" 39#include "dss_features.h" 40 41static struct { 42 struct platform_device *pdev; 43 44 struct regulator *vdds_dsi_reg; 45 struct regulator *vdds_sdi_reg; 46} core; 47 48static char *def_disp_name; 49module_param_named(def_disp, def_disp_name, charp, 0); 50MODULE_PARM_DESC(def_disp, "default display name"); 51 52#ifdef DEBUG 53bool dss_debug; 54module_param_named(debug, dss_debug, bool, 0644); 55#endif 56 57static int omap_dss_register_device(struct omap_dss_device *); 58static void omap_dss_unregister_device(struct omap_dss_device *); 59 60/* REGULATORS */ 61 62struct regulator *dss_get_vdds_dsi(void) 63{ 64 struct regulator *reg; 65 66 if (core.vdds_dsi_reg != NULL) 67 return core.vdds_dsi_reg; 68 69 reg = regulator_get(&core.pdev->dev, "vdds_dsi"); 70 if (!IS_ERR(reg)) 71 core.vdds_dsi_reg = reg; 72 73 return reg; 74} 75 76struct regulator *dss_get_vdds_sdi(void) 77{ 78 struct regulator *reg; 79 80 if (core.vdds_sdi_reg != NULL) 81 return core.vdds_sdi_reg; 82 83 reg = regulator_get(&core.pdev->dev, "vdds_sdi"); 84 if (!IS_ERR(reg)) 85 core.vdds_sdi_reg = reg; 86 87 return reg; 88} 89 90#if defined(CONFIG_DEBUG_FS) && defined(CONFIG_OMAP2_DSS_DEBUG_SUPPORT) 91static int dss_debug_show(struct seq_file *s, void *unused) 92{ 93 void (*func)(struct seq_file *) = s->private; 94 func(s); 95 return 0; 96} 97 98static int dss_debug_open(struct inode *inode, struct file *file) 99{ 100 return single_open(file, dss_debug_show, inode->i_private); 101} 102 103static const struct file_operations dss_debug_fops = { 104 .open = dss_debug_open, 105 .read = seq_read, 106 .llseek = seq_lseek, 107 .release = single_release, 108}; 109 110static struct dentry *dss_debugfs_dir; 111 112static int dss_initialize_debugfs(void) 113{ 114 dss_debugfs_dir = debugfs_create_dir("omapdss", NULL); 115 if (IS_ERR(dss_debugfs_dir)) { 116 int err = PTR_ERR(dss_debugfs_dir); 117 dss_debugfs_dir = NULL; 118 return err; 119 } 120 121 debugfs_create_file("clk", S_IRUGO, dss_debugfs_dir, 122 &dss_debug_dump_clocks, &dss_debug_fops); 123 124#ifdef CONFIG_OMAP2_DSS_COLLECT_IRQ_STATS 125 debugfs_create_file("dispc_irq", S_IRUGO, dss_debugfs_dir, 126 &dispc_dump_irqs, &dss_debug_fops); 127#endif 128 129#if defined(CONFIG_OMAP2_DSS_DSI) && defined(CONFIG_OMAP2_DSS_COLLECT_IRQ_STATS) 130 dsi_create_debugfs_files_irq(dss_debugfs_dir, &dss_debug_fops); 131#endif 132 133 debugfs_create_file("dss", S_IRUGO, dss_debugfs_dir, 134 &dss_dump_regs, &dss_debug_fops); 135 debugfs_create_file("dispc", S_IRUGO, dss_debugfs_dir, 136 &dispc_dump_regs, &dss_debug_fops); 137#ifdef CONFIG_OMAP2_DSS_RFBI 138 debugfs_create_file("rfbi", S_IRUGO, dss_debugfs_dir, 139 &rfbi_dump_regs, &dss_debug_fops); 140#endif 141#ifdef CONFIG_OMAP2_DSS_DSI 142 dsi_create_debugfs_files_reg(dss_debugfs_dir, &dss_debug_fops); 143#endif 144#ifdef CONFIG_OMAP2_DSS_VENC 145 debugfs_create_file("venc", S_IRUGO, dss_debugfs_dir, 146 &venc_dump_regs, &dss_debug_fops); 147#endif 148#ifdef CONFIG_OMAP4_DSS_HDMI 149 debugfs_create_file("hdmi", S_IRUGO, dss_debugfs_dir, 150 &hdmi_dump_regs, &dss_debug_fops); 151#endif 152 return 0; 153} 154 155static void dss_uninitialize_debugfs(void) 156{ 157 if (dss_debugfs_dir) 158 debugfs_remove_recursive(dss_debugfs_dir); 159} 160#else /* CONFIG_DEBUG_FS && CONFIG_OMAP2_DSS_DEBUG_SUPPORT */ 161static inline int dss_initialize_debugfs(void) 162{ 163 return 0; 164} 165static inline void dss_uninitialize_debugfs(void) 166{ 167} 168#endif /* CONFIG_DEBUG_FS && CONFIG_OMAP2_DSS_DEBUG_SUPPORT */ 169 170/* PLATFORM DEVICE */ 171static int omap_dss_probe(struct platform_device *pdev) 172{ 173 struct omap_dss_board_info *pdata = pdev->dev.platform_data; 174 int r; 175 int i; 176 177 core.pdev = pdev; 178 179 dss_features_init(); 180 181 dss_apply_init(); 182 183 dss_init_overlay_managers(pdev); 184 dss_init_overlays(pdev); 185 186 r = dss_init_platform_driver(); 187 if (r) { 188 DSSERR("Failed to initialize DSS platform driver\n"); 189 goto err_dss; 190 } 191 192 r = dispc_init_platform_driver(); 193 if (r) { 194 DSSERR("Failed to initialize dispc platform driver\n"); 195 goto err_dispc; 196 } 197 198 r = rfbi_init_platform_driver(); 199 if (r) { 200 DSSERR("Failed to initialize rfbi platform driver\n"); 201 goto err_rfbi; 202 } 203 204 r = venc_init_platform_driver(); 205 if (r) { 206 DSSERR("Failed to initialize venc platform driver\n"); 207 goto err_venc; 208 } 209 210 r = dsi_init_platform_driver(); 211 if (r) { 212 DSSERR("Failed to initialize DSI platform driver\n"); 213 goto err_dsi; 214 } 215 216 r = hdmi_init_platform_driver(); 217 if (r) { 218 DSSERR("Failed to initialize hdmi\n"); 219 goto err_hdmi; 220 } 221 222 r = dss_initialize_debugfs(); 223 if (r) 224 goto err_debugfs; 225 226 for (i = 0; i < pdata->num_devices; ++i) { 227 struct omap_dss_device *dssdev = pdata->devices[i]; 228 229 r = omap_dss_register_device(dssdev); 230 if (r) { 231 DSSERR("device %d %s register failed %d\n", i, 232 dssdev->name ?: "unnamed", r); 233 234 while (--i >= 0) 235 omap_dss_unregister_device(pdata->devices[i]); 236 237 goto err_register; 238 } 239 240 if (def_disp_name && strcmp(def_disp_name, dssdev->name) == 0) 241 pdata->default_device = dssdev; 242 } 243 244 return 0; 245 246err_register: 247 dss_uninitialize_debugfs(); 248err_debugfs: 249 hdmi_uninit_platform_driver(); 250err_hdmi: 251 dsi_uninit_platform_driver(); 252err_dsi: 253 venc_uninit_platform_driver(); 254err_venc: 255 dispc_uninit_platform_driver(); 256err_dispc: 257 rfbi_uninit_platform_driver(); 258err_rfbi: 259 dss_uninit_platform_driver(); 260err_dss: 261 262 return r; 263} 264 265static int omap_dss_remove(struct platform_device *pdev) 266{ 267 struct omap_dss_board_info *pdata = pdev->dev.platform_data; 268 int i; 269 270 dss_uninitialize_debugfs(); 271 272 hdmi_uninit_platform_driver(); 273 dsi_uninit_platform_driver(); 274 venc_uninit_platform_driver(); 275 rfbi_uninit_platform_driver(); 276 dispc_uninit_platform_driver(); 277 dss_uninit_platform_driver(); 278 279 dss_uninit_overlays(pdev); 280 dss_uninit_overlay_managers(pdev); 281 282 for (i = 0; i < pdata->num_devices; ++i) 283 omap_dss_unregister_device(pdata->devices[i]); 284 285 return 0; 286} 287 288static void omap_dss_shutdown(struct platform_device *pdev) 289{ 290 DSSDBG("shutdown\n"); 291 dss_disable_all_devices(); 292} 293 294static int omap_dss_suspend(struct platform_device *pdev, pm_message_t state) 295{ 296 DSSDBG("suspend %d\n", state.event); 297 298 return dss_suspend_all_devices(); 299} 300 301static int omap_dss_resume(struct platform_device *pdev) 302{ 303 DSSDBG("resume\n"); 304 305 return dss_resume_all_devices(); 306} 307 308static struct platform_driver omap_dss_driver = { 309 .probe = omap_dss_probe, 310 .remove = omap_dss_remove, 311 .shutdown = omap_dss_shutdown, 312 .suspend = omap_dss_suspend, 313 .resume = omap_dss_resume, 314 .driver = { 315 .name = "omapdss", 316 .owner = THIS_MODULE, 317 }, 318}; 319 320/* BUS */ 321static int dss_bus_match(struct device *dev, struct device_driver *driver) 322{ 323 struct omap_dss_device *dssdev = to_dss_device(dev); 324 325 DSSDBG("bus_match. dev %s/%s, drv %s\n", 326 dev_name(dev), dssdev->driver_name, driver->name); 327 328 return strcmp(dssdev->driver_name, driver->name) == 0; 329} 330 331static ssize_t device_name_show(struct device *dev, 332 struct device_attribute *attr, char *buf) 333{ 334 struct omap_dss_device *dssdev = to_dss_device(dev); 335 return snprintf(buf, PAGE_SIZE, "%s\n", 336 dssdev->name ? 337 dssdev->name : ""); 338} 339 340static struct device_attribute default_dev_attrs[] = { 341 __ATTR(name, S_IRUGO, device_name_show, NULL), 342 __ATTR_NULL, 343}; 344 345static ssize_t driver_name_show(struct device_driver *drv, char *buf) 346{ 347 struct omap_dss_driver *dssdrv = to_dss_driver(drv); 348 return snprintf(buf, PAGE_SIZE, "%s\n", 349 dssdrv->driver.name ? 350 dssdrv->driver.name : ""); 351} 352static struct driver_attribute default_drv_attrs[] = { 353 __ATTR(name, S_IRUGO, driver_name_show, NULL), 354 __ATTR_NULL, 355}; 356 357static struct bus_type dss_bus_type = { 358 .name = "omapdss", 359 .match = dss_bus_match, 360 .dev_attrs = default_dev_attrs, 361 .drv_attrs = default_drv_attrs, 362}; 363 364static void dss_bus_release(struct device *dev) 365{ 366 DSSDBG("bus_release\n"); 367} 368 369static struct device dss_bus = { 370 .release = dss_bus_release, 371}; 372 373struct bus_type *dss_get_bus(void) 374{ 375 return &dss_bus_type; 376} 377 378/* DRIVER */ 379static int dss_driver_probe(struct device *dev) 380{ 381 int r; 382 struct omap_dss_driver *dssdrv = to_dss_driver(dev->driver); 383 struct omap_dss_device *dssdev = to_dss_device(dev); 384 struct omap_dss_board_info *pdata = core.pdev->dev.platform_data; 385 bool force; 386 387 DSSDBG("driver_probe: dev %s/%s, drv %s\n", 388 dev_name(dev), dssdev->driver_name, 389 dssdrv->driver.name); 390 391 dss_init_device(core.pdev, dssdev); 392 393 force = pdata->default_device == dssdev; 394 dss_recheck_connections(dssdev, force); 395 396 r = dssdrv->probe(dssdev); 397 398 if (r) { 399 DSSERR("driver probe failed: %d\n", r); 400 dss_uninit_device(core.pdev, dssdev); 401 return r; 402 } 403 404 DSSDBG("probe done for device %s\n", dev_name(dev)); 405 406 dssdev->driver = dssdrv; 407 408 return 0; 409} 410 411static int dss_driver_remove(struct device *dev) 412{ 413 struct omap_dss_driver *dssdrv = to_dss_driver(dev->driver); 414 struct omap_dss_device *dssdev = to_dss_device(dev); 415 416 DSSDBG("driver_remove: dev %s/%s\n", dev_name(dev), 417 dssdev->driver_name); 418 419 dssdrv->remove(dssdev); 420 421 dss_uninit_device(core.pdev, dssdev); 422 423 dssdev->driver = NULL; 424 425 return 0; 426} 427 428int omap_dss_register_driver(struct omap_dss_driver *dssdriver) 429{ 430 dssdriver->driver.bus = &dss_bus_type; 431 dssdriver->driver.probe = dss_driver_probe; 432 dssdriver->driver.remove = dss_driver_remove; 433 434 if (dssdriver->get_resolution == NULL) 435 dssdriver->get_resolution = omapdss_default_get_resolution; 436 if (dssdriver->get_recommended_bpp == NULL) 437 dssdriver->get_recommended_bpp = 438 omapdss_default_get_recommended_bpp; 439 440 return driver_register(&dssdriver->driver); 441} 442EXPORT_SYMBOL(omap_dss_register_driver); 443 444void omap_dss_unregister_driver(struct omap_dss_driver *dssdriver) 445{ 446 driver_unregister(&dssdriver->driver); 447} 448EXPORT_SYMBOL(omap_dss_unregister_driver); 449 450/* DEVICE */ 451static void reset_device(struct device *dev, int check) 452{ 453 u8 *dev_p = (u8 *)dev; 454 u8 *dev_end = dev_p + sizeof(*dev); 455 void *saved_pdata; 456 457 saved_pdata = dev->platform_data; 458 if (check) { 459 /* 460 * Check if there is any other setting than platform_data 461 * in struct device; warn that these will be reset by our 462 * init. 463 */ 464 dev->platform_data = NULL; 465 while (dev_p < dev_end) { 466 if (*dev_p) { 467 WARN("%s: struct device fields will be " 468 "discarded\n", 469 __func__); 470 break; 471 } 472 dev_p++; 473 } 474 } 475 memset(dev, 0, sizeof(*dev)); 476 dev->platform_data = saved_pdata; 477} 478 479 480static void omap_dss_dev_release(struct device *dev) 481{ 482 reset_device(dev, 0); 483} 484 485static int omap_dss_register_device(struct omap_dss_device *dssdev) 486{ 487 static int dev_num; 488 489 WARN_ON(!dssdev->driver_name); 490 491 reset_device(&dssdev->dev, 1); 492 dssdev->dev.bus = &dss_bus_type; 493 dssdev->dev.parent = &dss_bus; 494 dssdev->dev.release = omap_dss_dev_release; 495 dev_set_name(&dssdev->dev, "display%d", dev_num++); 496 return device_register(&dssdev->dev); 497} 498 499static void omap_dss_unregister_device(struct omap_dss_device *dssdev) 500{ 501 device_unregister(&dssdev->dev); 502} 503 504/* BUS */ 505static int omap_dss_bus_register(void) 506{ 507 int r; 508 509 r = bus_register(&dss_bus_type); 510 if (r) { 511 DSSERR("bus register failed\n"); 512 return r; 513 } 514 515 dev_set_name(&dss_bus, "omapdss"); 516 r = device_register(&dss_bus); 517 if (r) { 518 DSSERR("bus driver register failed\n"); 519 bus_unregister(&dss_bus_type); 520 return r; 521 } 522 523 return 0; 524} 525 526/* INIT */ 527 528#ifdef CONFIG_OMAP2_DSS_MODULE 529static void omap_dss_bus_unregister(void) 530{ 531 device_unregister(&dss_bus); 532 533 bus_unregister(&dss_bus_type); 534} 535 536static int __init omap_dss_init(void) 537{ 538 int r; 539 540 r = omap_dss_bus_register(); 541 if (r) 542 return r; 543 544 r = platform_driver_register(&omap_dss_driver); 545 if (r) { 546 omap_dss_bus_unregister(); 547 return r; 548 } 549 550 return 0; 551} 552 553static void __exit omap_dss_exit(void) 554{ 555 if (core.vdds_dsi_reg != NULL) { 556 regulator_put(core.vdds_dsi_reg); 557 core.vdds_dsi_reg = NULL; 558 } 559 560 if (core.vdds_sdi_reg != NULL) { 561 regulator_put(core.vdds_sdi_reg); 562 core.vdds_sdi_reg = NULL; 563 } 564 565 platform_driver_unregister(&omap_dss_driver); 566 567 omap_dss_bus_unregister(); 568} 569 570module_init(omap_dss_init); 571module_exit(omap_dss_exit); 572#else 573static int __init omap_dss_init(void) 574{ 575 return omap_dss_bus_register(); 576} 577 578static int __init omap_dss_init2(void) 579{ 580 return platform_driver_register(&omap_dss_driver); 581} 582 583core_initcall(omap_dss_init); 584device_initcall(omap_dss_init2); 585#endif 586 587MODULE_AUTHOR("Tomi Valkeinen <tomi.valkeinen@nokia.com>"); 588MODULE_DESCRIPTION("OMAP2/3 Display Subsystem"); 589MODULE_LICENSE("GPL v2"); 590 591