Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

at v3.4-rc7 609 lines 13 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 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_initialize_debugfs(); 187 if (r) 188 goto err_debugfs; 189 190 for (i = 0; i < pdata->num_devices; ++i) { 191 struct omap_dss_device *dssdev = pdata->devices[i]; 192 193 r = omap_dss_register_device(dssdev); 194 if (r) { 195 DSSERR("device %d %s register failed %d\n", i, 196 dssdev->name ?: "unnamed", r); 197 198 while (--i >= 0) 199 omap_dss_unregister_device(pdata->devices[i]); 200 201 goto err_register; 202 } 203 204 if (def_disp_name && strcmp(def_disp_name, dssdev->name) == 0) 205 pdata->default_device = dssdev; 206 } 207 208 return 0; 209 210err_register: 211 dss_uninitialize_debugfs(); 212err_debugfs: 213 214 return r; 215} 216 217static int omap_dss_remove(struct platform_device *pdev) 218{ 219 struct omap_dss_board_info *pdata = pdev->dev.platform_data; 220 int i; 221 222 dss_uninitialize_debugfs(); 223 224 dss_uninit_overlays(pdev); 225 dss_uninit_overlay_managers(pdev); 226 227 for (i = 0; i < pdata->num_devices; ++i) 228 omap_dss_unregister_device(pdata->devices[i]); 229 230 return 0; 231} 232 233static void omap_dss_shutdown(struct platform_device *pdev) 234{ 235 DSSDBG("shutdown\n"); 236 dss_disable_all_devices(); 237} 238 239static int omap_dss_suspend(struct platform_device *pdev, pm_message_t state) 240{ 241 DSSDBG("suspend %d\n", state.event); 242 243 return dss_suspend_all_devices(); 244} 245 246static int omap_dss_resume(struct platform_device *pdev) 247{ 248 DSSDBG("resume\n"); 249 250 return dss_resume_all_devices(); 251} 252 253static struct platform_driver omap_dss_driver = { 254 .probe = omap_dss_probe, 255 .remove = omap_dss_remove, 256 .shutdown = omap_dss_shutdown, 257 .suspend = omap_dss_suspend, 258 .resume = omap_dss_resume, 259 .driver = { 260 .name = "omapdss", 261 .owner = THIS_MODULE, 262 }, 263}; 264 265/* BUS */ 266static int dss_bus_match(struct device *dev, struct device_driver *driver) 267{ 268 struct omap_dss_device *dssdev = to_dss_device(dev); 269 270 DSSDBG("bus_match. dev %s/%s, drv %s\n", 271 dev_name(dev), dssdev->driver_name, driver->name); 272 273 return strcmp(dssdev->driver_name, driver->name) == 0; 274} 275 276static ssize_t device_name_show(struct device *dev, 277 struct device_attribute *attr, char *buf) 278{ 279 struct omap_dss_device *dssdev = to_dss_device(dev); 280 return snprintf(buf, PAGE_SIZE, "%s\n", 281 dssdev->name ? 282 dssdev->name : ""); 283} 284 285static struct device_attribute default_dev_attrs[] = { 286 __ATTR(name, S_IRUGO, device_name_show, NULL), 287 __ATTR_NULL, 288}; 289 290static ssize_t driver_name_show(struct device_driver *drv, char *buf) 291{ 292 struct omap_dss_driver *dssdrv = to_dss_driver(drv); 293 return snprintf(buf, PAGE_SIZE, "%s\n", 294 dssdrv->driver.name ? 295 dssdrv->driver.name : ""); 296} 297static struct driver_attribute default_drv_attrs[] = { 298 __ATTR(name, S_IRUGO, driver_name_show, NULL), 299 __ATTR_NULL, 300}; 301 302static struct bus_type dss_bus_type = { 303 .name = "omapdss", 304 .match = dss_bus_match, 305 .dev_attrs = default_dev_attrs, 306 .drv_attrs = default_drv_attrs, 307}; 308 309static void dss_bus_release(struct device *dev) 310{ 311 DSSDBG("bus_release\n"); 312} 313 314static struct device dss_bus = { 315 .release = dss_bus_release, 316}; 317 318struct bus_type *dss_get_bus(void) 319{ 320 return &dss_bus_type; 321} 322 323/* DRIVER */ 324static int dss_driver_probe(struct device *dev) 325{ 326 int r; 327 struct omap_dss_driver *dssdrv = to_dss_driver(dev->driver); 328 struct omap_dss_device *dssdev = to_dss_device(dev); 329 struct omap_dss_board_info *pdata = core.pdev->dev.platform_data; 330 bool force; 331 332 DSSDBG("driver_probe: dev %s/%s, drv %s\n", 333 dev_name(dev), dssdev->driver_name, 334 dssdrv->driver.name); 335 336 dss_init_device(core.pdev, dssdev); 337 338 force = pdata->default_device == dssdev; 339 dss_recheck_connections(dssdev, force); 340 341 r = dssdrv->probe(dssdev); 342 343 if (r) { 344 DSSERR("driver probe failed: %d\n", r); 345 dss_uninit_device(core.pdev, dssdev); 346 return r; 347 } 348 349 DSSDBG("probe done for device %s\n", dev_name(dev)); 350 351 dssdev->driver = dssdrv; 352 353 return 0; 354} 355 356static int dss_driver_remove(struct device *dev) 357{ 358 struct omap_dss_driver *dssdrv = to_dss_driver(dev->driver); 359 struct omap_dss_device *dssdev = to_dss_device(dev); 360 361 DSSDBG("driver_remove: dev %s/%s\n", dev_name(dev), 362 dssdev->driver_name); 363 364 dssdrv->remove(dssdev); 365 366 dss_uninit_device(core.pdev, dssdev); 367 368 dssdev->driver = NULL; 369 370 return 0; 371} 372 373int omap_dss_register_driver(struct omap_dss_driver *dssdriver) 374{ 375 dssdriver->driver.bus = &dss_bus_type; 376 dssdriver->driver.probe = dss_driver_probe; 377 dssdriver->driver.remove = dss_driver_remove; 378 379 if (dssdriver->get_resolution == NULL) 380 dssdriver->get_resolution = omapdss_default_get_resolution; 381 if (dssdriver->get_recommended_bpp == NULL) 382 dssdriver->get_recommended_bpp = 383 omapdss_default_get_recommended_bpp; 384 385 return driver_register(&dssdriver->driver); 386} 387EXPORT_SYMBOL(omap_dss_register_driver); 388 389void omap_dss_unregister_driver(struct omap_dss_driver *dssdriver) 390{ 391 driver_unregister(&dssdriver->driver); 392} 393EXPORT_SYMBOL(omap_dss_unregister_driver); 394 395/* DEVICE */ 396static void reset_device(struct device *dev, int check) 397{ 398 u8 *dev_p = (u8 *)dev; 399 u8 *dev_end = dev_p + sizeof(*dev); 400 void *saved_pdata; 401 402 saved_pdata = dev->platform_data; 403 if (check) { 404 /* 405 * Check if there is any other setting than platform_data 406 * in struct device; warn that these will be reset by our 407 * init. 408 */ 409 dev->platform_data = NULL; 410 while (dev_p < dev_end) { 411 if (*dev_p) { 412 WARN("%s: struct device fields will be " 413 "discarded\n", 414 __func__); 415 break; 416 } 417 dev_p++; 418 } 419 } 420 memset(dev, 0, sizeof(*dev)); 421 dev->platform_data = saved_pdata; 422} 423 424 425static void omap_dss_dev_release(struct device *dev) 426{ 427 reset_device(dev, 0); 428} 429 430static int omap_dss_register_device(struct omap_dss_device *dssdev) 431{ 432 static int dev_num; 433 434 WARN_ON(!dssdev->driver_name); 435 436 reset_device(&dssdev->dev, 1); 437 dssdev->dev.bus = &dss_bus_type; 438 dssdev->dev.parent = &dss_bus; 439 dssdev->dev.release = omap_dss_dev_release; 440 dev_set_name(&dssdev->dev, "display%d", dev_num++); 441 return device_register(&dssdev->dev); 442} 443 444static void omap_dss_unregister_device(struct omap_dss_device *dssdev) 445{ 446 device_unregister(&dssdev->dev); 447} 448 449/* BUS */ 450static int omap_dss_bus_register(void) 451{ 452 int r; 453 454 r = bus_register(&dss_bus_type); 455 if (r) { 456 DSSERR("bus register failed\n"); 457 return r; 458 } 459 460 dev_set_name(&dss_bus, "omapdss"); 461 r = device_register(&dss_bus); 462 if (r) { 463 DSSERR("bus driver register failed\n"); 464 bus_unregister(&dss_bus_type); 465 return r; 466 } 467 468 return 0; 469} 470 471/* INIT */ 472 473static int __init omap_dss_register_drivers(void) 474{ 475 int r; 476 477 r = platform_driver_register(&omap_dss_driver); 478 if (r) 479 return r; 480 481 r = dss_init_platform_driver(); 482 if (r) { 483 DSSERR("Failed to initialize DSS platform driver\n"); 484 goto err_dss; 485 } 486 487 r = dispc_init_platform_driver(); 488 if (r) { 489 DSSERR("Failed to initialize dispc platform driver\n"); 490 goto err_dispc; 491 } 492 493 r = rfbi_init_platform_driver(); 494 if (r) { 495 DSSERR("Failed to initialize rfbi platform driver\n"); 496 goto err_rfbi; 497 } 498 499 r = venc_init_platform_driver(); 500 if (r) { 501 DSSERR("Failed to initialize venc platform driver\n"); 502 goto err_venc; 503 } 504 505 r = dsi_init_platform_driver(); 506 if (r) { 507 DSSERR("Failed to initialize DSI platform driver\n"); 508 goto err_dsi; 509 } 510 511 r = hdmi_init_platform_driver(); 512 if (r) { 513 DSSERR("Failed to initialize hdmi\n"); 514 goto err_hdmi; 515 } 516 517 return 0; 518 519err_hdmi: 520 dsi_uninit_platform_driver(); 521err_dsi: 522 venc_uninit_platform_driver(); 523err_venc: 524 rfbi_uninit_platform_driver(); 525err_rfbi: 526 dispc_uninit_platform_driver(); 527err_dispc: 528 dss_uninit_platform_driver(); 529err_dss: 530 platform_driver_unregister(&omap_dss_driver); 531 532 return r; 533} 534 535static void __exit omap_dss_unregister_drivers(void) 536{ 537 hdmi_uninit_platform_driver(); 538 dsi_uninit_platform_driver(); 539 venc_uninit_platform_driver(); 540 rfbi_uninit_platform_driver(); 541 dispc_uninit_platform_driver(); 542 dss_uninit_platform_driver(); 543 544 platform_driver_unregister(&omap_dss_driver); 545} 546 547#ifdef CONFIG_OMAP2_DSS_MODULE 548static void omap_dss_bus_unregister(void) 549{ 550 device_unregister(&dss_bus); 551 552 bus_unregister(&dss_bus_type); 553} 554 555static int __init omap_dss_init(void) 556{ 557 int r; 558 559 r = omap_dss_bus_register(); 560 if (r) 561 return r; 562 563 r = omap_dss_register_drivers(); 564 if (r) { 565 omap_dss_bus_unregister(); 566 return r; 567 } 568 569 return 0; 570} 571 572static void __exit omap_dss_exit(void) 573{ 574 if (core.vdds_dsi_reg != NULL) { 575 regulator_put(core.vdds_dsi_reg); 576 core.vdds_dsi_reg = NULL; 577 } 578 579 if (core.vdds_sdi_reg != NULL) { 580 regulator_put(core.vdds_sdi_reg); 581 core.vdds_sdi_reg = NULL; 582 } 583 584 omap_dss_unregister_drivers(); 585 586 omap_dss_bus_unregister(); 587} 588 589module_init(omap_dss_init); 590module_exit(omap_dss_exit); 591#else 592static int __init omap_dss_init(void) 593{ 594 return omap_dss_bus_register(); 595} 596 597static int __init omap_dss_init2(void) 598{ 599 return omap_dss_register_drivers(); 600} 601 602core_initcall(omap_dss_init); 603device_initcall(omap_dss_init2); 604#endif 605 606MODULE_AUTHOR("Tomi Valkeinen <tomi.valkeinen@nokia.com>"); 607MODULE_DESCRIPTION("OMAP2/3 Display Subsystem"); 608MODULE_LICENSE("GPL v2"); 609