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 <plat/display.h> 37#include <plat/clock.h> 38 39#include "dss.h" 40 41static struct { 42 struct platform_device *pdev; 43 int ctx_id; 44 45 struct clk *dss_ick; 46 struct clk *dss1_fck; 47 struct clk *dss2_fck; 48 struct clk *dss_54m_fck; 49 struct clk *dss_96m_fck; 50 unsigned num_clks_enabled; 51 52 struct regulator *vdds_dsi_reg; 53 struct regulator *vdds_sdi_reg; 54 struct regulator *vdda_dac_reg; 55} core; 56 57static void dss_clk_enable_all_no_ctx(void); 58static void dss_clk_disable_all_no_ctx(void); 59static void dss_clk_enable_no_ctx(enum dss_clock clks); 60static void dss_clk_disable_no_ctx(enum dss_clock clks); 61 62static char *def_disp_name; 63module_param_named(def_disp, def_disp_name, charp, 0); 64MODULE_PARM_DESC(def_disp_name, "default display name"); 65 66#ifdef DEBUG 67unsigned int dss_debug; 68module_param_named(debug, dss_debug, bool, 0644); 69#endif 70 71/* CONTEXT */ 72static int dss_get_ctx_id(void) 73{ 74 struct omap_dss_board_info *pdata = core.pdev->dev.platform_data; 75 int r; 76 77 if (!pdata->get_last_off_on_transaction_id) 78 return 0; 79 r = pdata->get_last_off_on_transaction_id(&core.pdev->dev); 80 if (r < 0) { 81 dev_err(&core.pdev->dev, "getting transaction ID failed, " 82 "will force context restore\n"); 83 r = -1; 84 } 85 return r; 86} 87 88int dss_need_ctx_restore(void) 89{ 90 int id = dss_get_ctx_id(); 91 92 if (id < 0 || id != core.ctx_id) { 93 DSSDBG("ctx id %d -> id %d\n", 94 core.ctx_id, id); 95 core.ctx_id = id; 96 return 1; 97 } else { 98 return 0; 99 } 100} 101 102static void save_all_ctx(void) 103{ 104 DSSDBG("save context\n"); 105 106 dss_clk_enable_no_ctx(DSS_CLK_ICK | DSS_CLK_FCK1); 107 108 dss_save_context(); 109 dispc_save_context(); 110#ifdef CONFIG_OMAP2_DSS_DSI 111 dsi_save_context(); 112#endif 113 114 dss_clk_disable_no_ctx(DSS_CLK_ICK | DSS_CLK_FCK1); 115} 116 117static void restore_all_ctx(void) 118{ 119 DSSDBG("restore context\n"); 120 121 dss_clk_enable_all_no_ctx(); 122 123 dss_restore_context(); 124 dispc_restore_context(); 125#ifdef CONFIG_OMAP2_DSS_DSI 126 dsi_restore_context(); 127#endif 128 129 dss_clk_disable_all_no_ctx(); 130} 131 132#if defined(CONFIG_DEBUG_FS) && defined(CONFIG_OMAP2_DSS_DEBUG_SUPPORT) 133/* CLOCKS */ 134static void core_dump_clocks(struct seq_file *s) 135{ 136 int i; 137 struct clk *clocks[5] = { 138 core.dss_ick, 139 core.dss1_fck, 140 core.dss2_fck, 141 core.dss_54m_fck, 142 core.dss_96m_fck 143 }; 144 145 seq_printf(s, "- CORE -\n"); 146 147 seq_printf(s, "internal clk count\t\t%u\n", core.num_clks_enabled); 148 149 for (i = 0; i < 5; i++) { 150 if (!clocks[i]) 151 continue; 152 seq_printf(s, "%-15s\t%lu\t%d\n", 153 clocks[i]->name, 154 clk_get_rate(clocks[i]), 155 clocks[i]->usecount); 156 } 157} 158#endif /* defined(CONFIG_DEBUG_FS) && defined(CONFIG_OMAP2_DSS_DEBUG_SUPPORT) */ 159 160static int dss_get_clock(struct clk **clock, const char *clk_name) 161{ 162 struct clk *clk; 163 164 clk = clk_get(&core.pdev->dev, clk_name); 165 166 if (IS_ERR(clk)) { 167 DSSERR("can't get clock %s", clk_name); 168 return PTR_ERR(clk); 169 } 170 171 *clock = clk; 172 173 DSSDBG("clk %s, rate %ld\n", clk_name, clk_get_rate(clk)); 174 175 return 0; 176} 177 178static int dss_get_clocks(void) 179{ 180 int r; 181 182 core.dss_ick = NULL; 183 core.dss1_fck = NULL; 184 core.dss2_fck = NULL; 185 core.dss_54m_fck = NULL; 186 core.dss_96m_fck = NULL; 187 188 r = dss_get_clock(&core.dss_ick, "ick"); 189 if (r) 190 goto err; 191 192 r = dss_get_clock(&core.dss1_fck, "dss1_fck"); 193 if (r) 194 goto err; 195 196 r = dss_get_clock(&core.dss2_fck, "dss2_fck"); 197 if (r) 198 goto err; 199 200 r = dss_get_clock(&core.dss_54m_fck, "tv_fck"); 201 if (r) 202 goto err; 203 204 r = dss_get_clock(&core.dss_96m_fck, "video_fck"); 205 if (r) 206 goto err; 207 208 return 0; 209 210err: 211 if (core.dss_ick) 212 clk_put(core.dss_ick); 213 if (core.dss1_fck) 214 clk_put(core.dss1_fck); 215 if (core.dss2_fck) 216 clk_put(core.dss2_fck); 217 if (core.dss_54m_fck) 218 clk_put(core.dss_54m_fck); 219 if (core.dss_96m_fck) 220 clk_put(core.dss_96m_fck); 221 222 return r; 223} 224 225static void dss_put_clocks(void) 226{ 227 if (core.dss_96m_fck) 228 clk_put(core.dss_96m_fck); 229 clk_put(core.dss_54m_fck); 230 clk_put(core.dss1_fck); 231 clk_put(core.dss2_fck); 232 clk_put(core.dss_ick); 233} 234 235unsigned long dss_clk_get_rate(enum dss_clock clk) 236{ 237 switch (clk) { 238 case DSS_CLK_ICK: 239 return clk_get_rate(core.dss_ick); 240 case DSS_CLK_FCK1: 241 return clk_get_rate(core.dss1_fck); 242 case DSS_CLK_FCK2: 243 return clk_get_rate(core.dss2_fck); 244 case DSS_CLK_54M: 245 return clk_get_rate(core.dss_54m_fck); 246 case DSS_CLK_96M: 247 return clk_get_rate(core.dss_96m_fck); 248 } 249 250 BUG(); 251 return 0; 252} 253 254static unsigned count_clk_bits(enum dss_clock clks) 255{ 256 unsigned num_clks = 0; 257 258 if (clks & DSS_CLK_ICK) 259 ++num_clks; 260 if (clks & DSS_CLK_FCK1) 261 ++num_clks; 262 if (clks & DSS_CLK_FCK2) 263 ++num_clks; 264 if (clks & DSS_CLK_54M) 265 ++num_clks; 266 if (clks & DSS_CLK_96M) 267 ++num_clks; 268 269 return num_clks; 270} 271 272static void dss_clk_enable_no_ctx(enum dss_clock clks) 273{ 274 unsigned num_clks = count_clk_bits(clks); 275 276 if (clks & DSS_CLK_ICK) 277 clk_enable(core.dss_ick); 278 if (clks & DSS_CLK_FCK1) 279 clk_enable(core.dss1_fck); 280 if (clks & DSS_CLK_FCK2) 281 clk_enable(core.dss2_fck); 282 if (clks & DSS_CLK_54M) 283 clk_enable(core.dss_54m_fck); 284 if (clks & DSS_CLK_96M) 285 clk_enable(core.dss_96m_fck); 286 287 core.num_clks_enabled += num_clks; 288} 289 290void dss_clk_enable(enum dss_clock clks) 291{ 292 bool check_ctx = core.num_clks_enabled == 0; 293 294 dss_clk_enable_no_ctx(clks); 295 296 if (check_ctx && cpu_is_omap34xx() && dss_need_ctx_restore()) 297 restore_all_ctx(); 298} 299 300static void dss_clk_disable_no_ctx(enum dss_clock clks) 301{ 302 unsigned num_clks = count_clk_bits(clks); 303 304 if (clks & DSS_CLK_ICK) 305 clk_disable(core.dss_ick); 306 if (clks & DSS_CLK_FCK1) 307 clk_disable(core.dss1_fck); 308 if (clks & DSS_CLK_FCK2) 309 clk_disable(core.dss2_fck); 310 if (clks & DSS_CLK_54M) 311 clk_disable(core.dss_54m_fck); 312 if (clks & DSS_CLK_96M) 313 clk_disable(core.dss_96m_fck); 314 315 core.num_clks_enabled -= num_clks; 316} 317 318void dss_clk_disable(enum dss_clock clks) 319{ 320 if (cpu_is_omap34xx()) { 321 unsigned num_clks = count_clk_bits(clks); 322 323 BUG_ON(core.num_clks_enabled < num_clks); 324 325 if (core.num_clks_enabled == num_clks) 326 save_all_ctx(); 327 } 328 329 dss_clk_disable_no_ctx(clks); 330} 331 332static void dss_clk_enable_all_no_ctx(void) 333{ 334 enum dss_clock clks; 335 336 clks = DSS_CLK_ICK | DSS_CLK_FCK1 | DSS_CLK_FCK2 | DSS_CLK_54M; 337 if (cpu_is_omap34xx()) 338 clks |= DSS_CLK_96M; 339 dss_clk_enable_no_ctx(clks); 340} 341 342static void dss_clk_disable_all_no_ctx(void) 343{ 344 enum dss_clock clks; 345 346 clks = DSS_CLK_ICK | DSS_CLK_FCK1 | DSS_CLK_FCK2 | DSS_CLK_54M; 347 if (cpu_is_omap34xx()) 348 clks |= DSS_CLK_96M; 349 dss_clk_disable_no_ctx(clks); 350} 351 352static void dss_clk_disable_all(void) 353{ 354 enum dss_clock clks; 355 356 clks = DSS_CLK_ICK | DSS_CLK_FCK1 | DSS_CLK_FCK2 | DSS_CLK_54M; 357 if (cpu_is_omap34xx()) 358 clks |= DSS_CLK_96M; 359 dss_clk_disable(clks); 360} 361 362/* REGULATORS */ 363 364struct regulator *dss_get_vdds_dsi(void) 365{ 366 struct regulator *reg; 367 368 if (core.vdds_dsi_reg != NULL) 369 return core.vdds_dsi_reg; 370 371 reg = regulator_get(&core.pdev->dev, "vdds_dsi"); 372 if (!IS_ERR(reg)) 373 core.vdds_dsi_reg = reg; 374 375 return reg; 376} 377 378struct regulator *dss_get_vdds_sdi(void) 379{ 380 struct regulator *reg; 381 382 if (core.vdds_sdi_reg != NULL) 383 return core.vdds_sdi_reg; 384 385 reg = regulator_get(&core.pdev->dev, "vdds_sdi"); 386 if (!IS_ERR(reg)) 387 core.vdds_sdi_reg = reg; 388 389 return reg; 390} 391 392struct regulator *dss_get_vdda_dac(void) 393{ 394 struct regulator *reg; 395 396 if (core.vdda_dac_reg != NULL) 397 return core.vdda_dac_reg; 398 399 reg = regulator_get(&core.pdev->dev, "vdda_dac"); 400 if (!IS_ERR(reg)) 401 core.vdda_dac_reg = reg; 402 403 return reg; 404} 405 406/* DEBUGFS */ 407#if defined(CONFIG_DEBUG_FS) && defined(CONFIG_OMAP2_DSS_DEBUG_SUPPORT) 408static void dss_debug_dump_clocks(struct seq_file *s) 409{ 410 core_dump_clocks(s); 411 dss_dump_clocks(s); 412 dispc_dump_clocks(s); 413#ifdef CONFIG_OMAP2_DSS_DSI 414 dsi_dump_clocks(s); 415#endif 416} 417 418static int dss_debug_show(struct seq_file *s, void *unused) 419{ 420 void (*func)(struct seq_file *) = s->private; 421 func(s); 422 return 0; 423} 424 425static int dss_debug_open(struct inode *inode, struct file *file) 426{ 427 return single_open(file, dss_debug_show, inode->i_private); 428} 429 430static const struct file_operations dss_debug_fops = { 431 .open = dss_debug_open, 432 .read = seq_read, 433 .llseek = seq_lseek, 434 .release = single_release, 435}; 436 437static struct dentry *dss_debugfs_dir; 438 439static int dss_initialize_debugfs(void) 440{ 441 dss_debugfs_dir = debugfs_create_dir("omapdss", NULL); 442 if (IS_ERR(dss_debugfs_dir)) { 443 int err = PTR_ERR(dss_debugfs_dir); 444 dss_debugfs_dir = NULL; 445 return err; 446 } 447 448 debugfs_create_file("clk", S_IRUGO, dss_debugfs_dir, 449 &dss_debug_dump_clocks, &dss_debug_fops); 450 451#ifdef CONFIG_OMAP2_DSS_COLLECT_IRQ_STATS 452 debugfs_create_file("dispc_irq", S_IRUGO, dss_debugfs_dir, 453 &dispc_dump_irqs, &dss_debug_fops); 454#endif 455 456#if defined(CONFIG_OMAP2_DSS_DSI) && defined(CONFIG_OMAP2_DSS_COLLECT_IRQ_STATS) 457 debugfs_create_file("dsi_irq", S_IRUGO, dss_debugfs_dir, 458 &dsi_dump_irqs, &dss_debug_fops); 459#endif 460 461 debugfs_create_file("dss", S_IRUGO, dss_debugfs_dir, 462 &dss_dump_regs, &dss_debug_fops); 463 debugfs_create_file("dispc", S_IRUGO, dss_debugfs_dir, 464 &dispc_dump_regs, &dss_debug_fops); 465#ifdef CONFIG_OMAP2_DSS_RFBI 466 debugfs_create_file("rfbi", S_IRUGO, dss_debugfs_dir, 467 &rfbi_dump_regs, &dss_debug_fops); 468#endif 469#ifdef CONFIG_OMAP2_DSS_DSI 470 debugfs_create_file("dsi", S_IRUGO, dss_debugfs_dir, 471 &dsi_dump_regs, &dss_debug_fops); 472#endif 473#ifdef CONFIG_OMAP2_DSS_VENC 474 debugfs_create_file("venc", S_IRUGO, dss_debugfs_dir, 475 &venc_dump_regs, &dss_debug_fops); 476#endif 477 return 0; 478} 479 480static void dss_uninitialize_debugfs(void) 481{ 482 if (dss_debugfs_dir) 483 debugfs_remove_recursive(dss_debugfs_dir); 484} 485#else /* CONFIG_DEBUG_FS && CONFIG_OMAP2_DSS_DEBUG_SUPPORT */ 486static inline int dss_initialize_debugfs(void) 487{ 488 return 0; 489} 490static inline void dss_uninitialize_debugfs(void) 491{ 492} 493#endif /* CONFIG_DEBUG_FS && CONFIG_OMAP2_DSS_DEBUG_SUPPORT */ 494 495/* PLATFORM DEVICE */ 496static int omap_dss_probe(struct platform_device *pdev) 497{ 498 struct omap_dss_board_info *pdata = pdev->dev.platform_data; 499 int skip_init = 0; 500 int r; 501 int i; 502 503 core.pdev = pdev; 504 505 dss_init_overlay_managers(pdev); 506 dss_init_overlays(pdev); 507 508 r = dss_get_clocks(); 509 if (r) 510 goto err_clocks; 511 512 dss_clk_enable_all_no_ctx(); 513 514 core.ctx_id = dss_get_ctx_id(); 515 DSSDBG("initial ctx id %u\n", core.ctx_id); 516 517#ifdef CONFIG_FB_OMAP_BOOTLOADER_INIT 518 /* DISPC_CONTROL */ 519 if (omap_readl(0x48050440) & 1) /* LCD enabled? */ 520 skip_init = 1; 521#endif 522 523 r = dss_init(skip_init); 524 if (r) { 525 DSSERR("Failed to initialize DSS\n"); 526 goto err_dss; 527 } 528 529 r = rfbi_init(); 530 if (r) { 531 DSSERR("Failed to initialize rfbi\n"); 532 goto err_rfbi; 533 } 534 535 r = dpi_init(pdev); 536 if (r) { 537 DSSERR("Failed to initialize dpi\n"); 538 goto err_dpi; 539 } 540 541 r = dispc_init(); 542 if (r) { 543 DSSERR("Failed to initialize dispc\n"); 544 goto err_dispc; 545 } 546 547 r = venc_init(pdev); 548 if (r) { 549 DSSERR("Failed to initialize venc\n"); 550 goto err_venc; 551 } 552 553 if (cpu_is_omap34xx()) { 554 r = sdi_init(skip_init); 555 if (r) { 556 DSSERR("Failed to initialize SDI\n"); 557 goto err_sdi; 558 } 559 560 r = dsi_init(pdev); 561 if (r) { 562 DSSERR("Failed to initialize DSI\n"); 563 goto err_dsi; 564 } 565 } 566 567 r = dss_initialize_debugfs(); 568 if (r) 569 goto err_debugfs; 570 571 for (i = 0; i < pdata->num_devices; ++i) { 572 struct omap_dss_device *dssdev = pdata->devices[i]; 573 574 r = omap_dss_register_device(dssdev); 575 if (r) { 576 DSSERR("device %d %s register failed %d\n", i, 577 dssdev->name ?: "unnamed", r); 578 579 while (--i >= 0) 580 omap_dss_unregister_device(pdata->devices[i]); 581 582 goto err_register; 583 } 584 585 if (def_disp_name && strcmp(def_disp_name, dssdev->name) == 0) 586 pdata->default_device = dssdev; 587 } 588 589 dss_clk_disable_all(); 590 591 return 0; 592 593err_register: 594 dss_uninitialize_debugfs(); 595err_debugfs: 596 if (cpu_is_omap34xx()) 597 dsi_exit(); 598err_dsi: 599 if (cpu_is_omap34xx()) 600 sdi_exit(); 601err_sdi: 602 venc_exit(); 603err_venc: 604 dispc_exit(); 605err_dispc: 606 dpi_exit(); 607err_dpi: 608 rfbi_exit(); 609err_rfbi: 610 dss_exit(); 611err_dss: 612 dss_clk_disable_all_no_ctx(); 613 dss_put_clocks(); 614err_clocks: 615 616 return r; 617} 618 619static int omap_dss_remove(struct platform_device *pdev) 620{ 621 struct omap_dss_board_info *pdata = pdev->dev.platform_data; 622 int i; 623 int c; 624 625 dss_uninitialize_debugfs(); 626 627 venc_exit(); 628 dispc_exit(); 629 dpi_exit(); 630 rfbi_exit(); 631 if (cpu_is_omap34xx()) { 632 dsi_exit(); 633 sdi_exit(); 634 } 635 636 dss_exit(); 637 638 /* these should be removed at some point */ 639 c = core.dss_ick->usecount; 640 if (c > 0) { 641 DSSERR("warning: dss_ick usecount %d, disabling\n", c); 642 while (c-- > 0) 643 clk_disable(core.dss_ick); 644 } 645 646 c = core.dss1_fck->usecount; 647 if (c > 0) { 648 DSSERR("warning: dss1_fck usecount %d, disabling\n", c); 649 while (c-- > 0) 650 clk_disable(core.dss1_fck); 651 } 652 653 c = core.dss2_fck->usecount; 654 if (c > 0) { 655 DSSERR("warning: dss2_fck usecount %d, disabling\n", c); 656 while (c-- > 0) 657 clk_disable(core.dss2_fck); 658 } 659 660 c = core.dss_54m_fck->usecount; 661 if (c > 0) { 662 DSSERR("warning: dss_54m_fck usecount %d, disabling\n", c); 663 while (c-- > 0) 664 clk_disable(core.dss_54m_fck); 665 } 666 667 if (core.dss_96m_fck) { 668 c = core.dss_96m_fck->usecount; 669 if (c > 0) { 670 DSSERR("warning: dss_96m_fck usecount %d, disabling\n", 671 c); 672 while (c-- > 0) 673 clk_disable(core.dss_96m_fck); 674 } 675 } 676 677 dss_put_clocks(); 678 679 dss_uninit_overlays(pdev); 680 dss_uninit_overlay_managers(pdev); 681 682 for (i = 0; i < pdata->num_devices; ++i) 683 omap_dss_unregister_device(pdata->devices[i]); 684 685 return 0; 686} 687 688static void omap_dss_shutdown(struct platform_device *pdev) 689{ 690 DSSDBG("shutdown\n"); 691 dss_disable_all_devices(); 692} 693 694static int omap_dss_suspend(struct platform_device *pdev, pm_message_t state) 695{ 696 DSSDBG("suspend %d\n", state.event); 697 698 return dss_suspend_all_devices(); 699} 700 701static int omap_dss_resume(struct platform_device *pdev) 702{ 703 DSSDBG("resume\n"); 704 705 return dss_resume_all_devices(); 706} 707 708static struct platform_driver omap_dss_driver = { 709 .probe = omap_dss_probe, 710 .remove = omap_dss_remove, 711 .shutdown = omap_dss_shutdown, 712 .suspend = omap_dss_suspend, 713 .resume = omap_dss_resume, 714 .driver = { 715 .name = "omapdss", 716 .owner = THIS_MODULE, 717 }, 718}; 719 720/* BUS */ 721static int dss_bus_match(struct device *dev, struct device_driver *driver) 722{ 723 struct omap_dss_device *dssdev = to_dss_device(dev); 724 725 DSSDBG("bus_match. dev %s/%s, drv %s\n", 726 dev_name(dev), dssdev->driver_name, driver->name); 727 728 return strcmp(dssdev->driver_name, driver->name) == 0; 729} 730 731static ssize_t device_name_show(struct device *dev, 732 struct device_attribute *attr, char *buf) 733{ 734 struct omap_dss_device *dssdev = to_dss_device(dev); 735 return snprintf(buf, PAGE_SIZE, "%s\n", 736 dssdev->name ? 737 dssdev->name : ""); 738} 739 740static struct device_attribute default_dev_attrs[] = { 741 __ATTR(name, S_IRUGO, device_name_show, NULL), 742 __ATTR_NULL, 743}; 744 745static ssize_t driver_name_show(struct device_driver *drv, char *buf) 746{ 747 struct omap_dss_driver *dssdrv = to_dss_driver(drv); 748 return snprintf(buf, PAGE_SIZE, "%s\n", 749 dssdrv->driver.name ? 750 dssdrv->driver.name : ""); 751} 752static struct driver_attribute default_drv_attrs[] = { 753 __ATTR(name, S_IRUGO, driver_name_show, NULL), 754 __ATTR_NULL, 755}; 756 757static struct bus_type dss_bus_type = { 758 .name = "omapdss", 759 .match = dss_bus_match, 760 .dev_attrs = default_dev_attrs, 761 .drv_attrs = default_drv_attrs, 762}; 763 764static void dss_bus_release(struct device *dev) 765{ 766 DSSDBG("bus_release\n"); 767} 768 769static struct device dss_bus = { 770 .release = dss_bus_release, 771}; 772 773struct bus_type *dss_get_bus(void) 774{ 775 return &dss_bus_type; 776} 777 778/* DRIVER */ 779static int dss_driver_probe(struct device *dev) 780{ 781 int r; 782 struct omap_dss_driver *dssdrv = to_dss_driver(dev->driver); 783 struct omap_dss_device *dssdev = to_dss_device(dev); 784 struct omap_dss_board_info *pdata = core.pdev->dev.platform_data; 785 bool force; 786 787 DSSDBG("driver_probe: dev %s/%s, drv %s\n", 788 dev_name(dev), dssdev->driver_name, 789 dssdrv->driver.name); 790 791 dss_init_device(core.pdev, dssdev); 792 793 force = pdata->default_device == dssdev; 794 dss_recheck_connections(dssdev, force); 795 796 r = dssdrv->probe(dssdev); 797 798 if (r) { 799 DSSERR("driver probe failed: %d\n", r); 800 dss_uninit_device(core.pdev, dssdev); 801 return r; 802 } 803 804 DSSDBG("probe done for device %s\n", dev_name(dev)); 805 806 dssdev->driver = dssdrv; 807 808 return 0; 809} 810 811static int dss_driver_remove(struct device *dev) 812{ 813 struct omap_dss_driver *dssdrv = to_dss_driver(dev->driver); 814 struct omap_dss_device *dssdev = to_dss_device(dev); 815 816 DSSDBG("driver_remove: dev %s/%s\n", dev_name(dev), 817 dssdev->driver_name); 818 819 dssdrv->remove(dssdev); 820 821 dss_uninit_device(core.pdev, dssdev); 822 823 dssdev->driver = NULL; 824 825 return 0; 826} 827 828int omap_dss_register_driver(struct omap_dss_driver *dssdriver) 829{ 830 dssdriver->driver.bus = &dss_bus_type; 831 dssdriver->driver.probe = dss_driver_probe; 832 dssdriver->driver.remove = dss_driver_remove; 833 834 if (dssdriver->get_resolution == NULL) 835 dssdriver->get_resolution = omapdss_default_get_resolution; 836 if (dssdriver->get_recommended_bpp == NULL) 837 dssdriver->get_recommended_bpp = 838 omapdss_default_get_recommended_bpp; 839 840 return driver_register(&dssdriver->driver); 841} 842EXPORT_SYMBOL(omap_dss_register_driver); 843 844void omap_dss_unregister_driver(struct omap_dss_driver *dssdriver) 845{ 846 driver_unregister(&dssdriver->driver); 847} 848EXPORT_SYMBOL(omap_dss_unregister_driver); 849 850/* DEVICE */ 851static void reset_device(struct device *dev, int check) 852{ 853 u8 *dev_p = (u8 *)dev; 854 u8 *dev_end = dev_p + sizeof(*dev); 855 void *saved_pdata; 856 857 saved_pdata = dev->platform_data; 858 if (check) { 859 /* 860 * Check if there is any other setting than platform_data 861 * in struct device; warn that these will be reset by our 862 * init. 863 */ 864 dev->platform_data = NULL; 865 while (dev_p < dev_end) { 866 if (*dev_p) { 867 WARN("%s: struct device fields will be " 868 "discarded\n", 869 __func__); 870 break; 871 } 872 dev_p++; 873 } 874 } 875 memset(dev, 0, sizeof(*dev)); 876 dev->platform_data = saved_pdata; 877} 878 879 880static void omap_dss_dev_release(struct device *dev) 881{ 882 reset_device(dev, 0); 883} 884 885int omap_dss_register_device(struct omap_dss_device *dssdev) 886{ 887 static int dev_num; 888 889 WARN_ON(!dssdev->driver_name); 890 891 reset_device(&dssdev->dev, 1); 892 dssdev->dev.bus = &dss_bus_type; 893 dssdev->dev.parent = &dss_bus; 894 dssdev->dev.release = omap_dss_dev_release; 895 dev_set_name(&dssdev->dev, "display%d", dev_num++); 896 return device_register(&dssdev->dev); 897} 898 899void omap_dss_unregister_device(struct omap_dss_device *dssdev) 900{ 901 device_unregister(&dssdev->dev); 902} 903 904/* BUS */ 905static int omap_dss_bus_register(void) 906{ 907 int r; 908 909 r = bus_register(&dss_bus_type); 910 if (r) { 911 DSSERR("bus register failed\n"); 912 return r; 913 } 914 915 dev_set_name(&dss_bus, "omapdss"); 916 r = device_register(&dss_bus); 917 if (r) { 918 DSSERR("bus driver register failed\n"); 919 bus_unregister(&dss_bus_type); 920 return r; 921 } 922 923 return 0; 924} 925 926/* INIT */ 927 928#ifdef CONFIG_OMAP2_DSS_MODULE 929static void omap_dss_bus_unregister(void) 930{ 931 device_unregister(&dss_bus); 932 933 bus_unregister(&dss_bus_type); 934} 935 936static int __init omap_dss_init(void) 937{ 938 int r; 939 940 r = omap_dss_bus_register(); 941 if (r) 942 return r; 943 944 r = platform_driver_register(&omap_dss_driver); 945 if (r) { 946 omap_dss_bus_unregister(); 947 return r; 948 } 949 950 return 0; 951} 952 953static void __exit omap_dss_exit(void) 954{ 955 if (core.vdds_dsi_reg != NULL) { 956 regulator_put(core.vdds_dsi_reg); 957 core.vdds_dsi_reg = NULL; 958 } 959 960 if (core.vdds_sdi_reg != NULL) { 961 regulator_put(core.vdds_sdi_reg); 962 core.vdds_sdi_reg = NULL; 963 } 964 965 if (core.vdda_dac_reg != NULL) { 966 regulator_put(core.vdda_dac_reg); 967 core.vdda_dac_reg = NULL; 968 } 969 970 platform_driver_unregister(&omap_dss_driver); 971 972 omap_dss_bus_unregister(); 973} 974 975module_init(omap_dss_init); 976module_exit(omap_dss_exit); 977#else 978static int __init omap_dss_init(void) 979{ 980 return omap_dss_bus_register(); 981} 982 983static int __init omap_dss_init2(void) 984{ 985 return platform_driver_register(&omap_dss_driver); 986} 987 988core_initcall(omap_dss_init); 989device_initcall(omap_dss_init2); 990#endif 991 992MODULE_AUTHOR("Tomi Valkeinen <tomi.valkeinen@nokia.com>"); 993MODULE_DESCRIPTION("OMAP2/3 Display Subsystem"); 994MODULE_LICENSE("GPL v2"); 995