1 /* 2 * HDMI interface DSS driver for TI's OMAP4 family of SoCs. 3 * Copyright (C) 2010-2011 Texas Instruments Incorporated - http://www.ti.com/ 4 * Authors: Yong Zhi 5 * Mythri pk <mythripk@ti.com> 6 * 7 * This program is free software; you can redistribute it and/or modify it 8 * under the terms of the GNU General Public License version 2 as published by 9 * the Free Software Foundation. 10 * 11 * This program is distributed in the hope that it will be useful, but WITHOUT 12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for 14 * more details. 15 * 16 * You should have received a copy of the GNU General Public License along with 17 * this program. If not, see <http://www.gnu.org/licenses/>. 18 */ 19 20 #define DSS_SUBSYS_NAME "HDMI" 21 22 #include <linux/kernel.h> 23 #include <linux/module.h> 24 #include <linux/err.h> 25 #include <linux/io.h> 26 #include <linux/interrupt.h> 27 #include <linux/mutex.h> 28 #include <linux/delay.h> 29 #include <linux/string.h> 30 #include <linux/platform_device.h> 31 #include <linux/pm_runtime.h> 32 #include <linux/clk.h> 33 #include <linux/gpio.h> 34 #include <linux/regulator/consumer.h> 35 #include <linux/component.h> 36 #include <video/omapfb_dss.h> 37 #include <sound/omap-hdmi-audio.h> 38 39 #include "hdmi4_core.h" 40 #include "dss.h" 41 #include "dss_features.h" 42 #include "hdmi.h" 43 44 static struct omap_hdmi hdmi; 45 46 static int hdmi_runtime_get(void) 47 { 48 int r; 49 50 DSSDBG("hdmi_runtime_get\n"); 51 52 r = pm_runtime_get_sync(&hdmi.pdev->dev); 53 WARN_ON(r < 0); 54 if (r < 0) 55 return r; 56 57 return 0; 58 } 59 60 static void hdmi_runtime_put(void) 61 { 62 int r; 63 64 DSSDBG("hdmi_runtime_put\n"); 65 66 r = pm_runtime_put_sync(&hdmi.pdev->dev); 67 WARN_ON(r < 0 && r != -ENOSYS); 68 } 69 70 static irqreturn_t hdmi_irq_handler(int irq, void *data) 71 { 72 struct hdmi_wp_data *wp = data; 73 u32 irqstatus; 74 75 irqstatus = hdmi_wp_get_irqstatus(wp); 76 hdmi_wp_set_irqstatus(wp, irqstatus); 77 78 if ((irqstatus & HDMI_IRQ_LINK_CONNECT) && 79 irqstatus & HDMI_IRQ_LINK_DISCONNECT) { 80 /* 81 * If we get both connect and disconnect interrupts at the same 82 * time, turn off the PHY, clear interrupts, and restart, which 83 * raises connect interrupt if a cable is connected, or nothing 84 * if cable is not connected. 85 */ 86 hdmi_wp_set_phy_pwr(wp, HDMI_PHYPWRCMD_OFF); 87 88 hdmi_wp_set_irqstatus(wp, HDMI_IRQ_LINK_CONNECT | 89 HDMI_IRQ_LINK_DISCONNECT); 90 91 hdmi_wp_set_phy_pwr(wp, HDMI_PHYPWRCMD_LDOON); 92 } else if (irqstatus & HDMI_IRQ_LINK_CONNECT) { 93 hdmi_wp_set_phy_pwr(wp, HDMI_PHYPWRCMD_TXON); 94 } else if (irqstatus & HDMI_IRQ_LINK_DISCONNECT) { 95 hdmi_wp_set_phy_pwr(wp, HDMI_PHYPWRCMD_LDOON); 96 } 97 98 return IRQ_HANDLED; 99 } 100 101 static int hdmi_init_regulator(void) 102 { 103 struct regulator *reg; 104 105 if (hdmi.vdda_reg != NULL) 106 return 0; 107 108 reg = devm_regulator_get(&hdmi.pdev->dev, "vdda"); 109 110 if (IS_ERR(reg)) { 111 if (PTR_ERR(reg) != -EPROBE_DEFER) 112 DSSERR("can't get VDDA regulator\n"); 113 return PTR_ERR(reg); 114 } 115 116 hdmi.vdda_reg = reg; 117 118 return 0; 119 } 120 121 static int hdmi_power_on_core(struct omap_dss_device *dssdev) 122 { 123 int r; 124 125 r = regulator_enable(hdmi.vdda_reg); 126 if (r) 127 return r; 128 129 r = hdmi_runtime_get(); 130 if (r) 131 goto err_runtime_get; 132 133 /* Make selection of HDMI in DSS */ 134 dss_select_hdmi_venc_clk_source(DSS_HDMI_M_PCLK); 135 136 hdmi.core_enabled = true; 137 138 return 0; 139 140 err_runtime_get: 141 regulator_disable(hdmi.vdda_reg); 142 143 return r; 144 } 145 146 static void hdmi_power_off_core(struct omap_dss_device *dssdev) 147 { 148 hdmi.core_enabled = false; 149 150 hdmi_runtime_put(); 151 regulator_disable(hdmi.vdda_reg); 152 } 153 154 static int hdmi_power_on_full(struct omap_dss_device *dssdev) 155 { 156 int r; 157 struct omap_video_timings *p; 158 struct omap_overlay_manager *mgr = hdmi.output.manager; 159 struct hdmi_wp_data *wp = &hdmi.wp; 160 struct dss_pll_clock_info hdmi_cinfo = { 0 }; 161 162 r = hdmi_power_on_core(dssdev); 163 if (r) 164 return r; 165 166 /* disable and clear irqs */ 167 hdmi_wp_clear_irqenable(wp, 0xffffffff); 168 hdmi_wp_set_irqstatus(wp, 0xffffffff); 169 170 p = &hdmi.cfg.timings; 171 172 DSSDBG("hdmi_power_on x_res= %d y_res = %d\n", p->x_res, p->y_res); 173 174 hdmi_pll_compute(&hdmi.pll, p->pixelclock, &hdmi_cinfo); 175 176 r = dss_pll_enable(&hdmi.pll.pll); 177 if (r) { 178 DSSERR("Failed to enable PLL\n"); 179 goto err_pll_enable; 180 } 181 182 r = dss_pll_set_config(&hdmi.pll.pll, &hdmi_cinfo); 183 if (r) { 184 DSSERR("Failed to configure PLL\n"); 185 goto err_pll_cfg; 186 } 187 188 r = hdmi_phy_configure(&hdmi.phy, hdmi_cinfo.clkdco, 189 hdmi_cinfo.clkout[0]); 190 if (r) { 191 DSSDBG("Failed to configure PHY\n"); 192 goto err_phy_cfg; 193 } 194 195 r = hdmi_wp_set_phy_pwr(wp, HDMI_PHYPWRCMD_LDOON); 196 if (r) 197 goto err_phy_pwr; 198 199 hdmi4_configure(&hdmi.core, &hdmi.wp, &hdmi.cfg); 200 201 /* bypass TV gamma table */ 202 dispc_enable_gamma_table(0); 203 204 /* tv size */ 205 dss_mgr_set_timings(mgr, p); 206 207 r = hdmi_wp_video_start(&hdmi.wp); 208 if (r) 209 goto err_vid_enable; 210 211 r = dss_mgr_enable(mgr); 212 if (r) 213 goto err_mgr_enable; 214 215 hdmi_wp_set_irqenable(wp, 216 HDMI_IRQ_LINK_CONNECT | HDMI_IRQ_LINK_DISCONNECT); 217 218 return 0; 219 220 err_mgr_enable: 221 hdmi_wp_video_stop(&hdmi.wp); 222 err_vid_enable: 223 hdmi_wp_set_phy_pwr(&hdmi.wp, HDMI_PHYPWRCMD_OFF); 224 err_phy_pwr: 225 err_phy_cfg: 226 err_pll_cfg: 227 dss_pll_disable(&hdmi.pll.pll); 228 err_pll_enable: 229 hdmi_power_off_core(dssdev); 230 return -EIO; 231 } 232 233 static void hdmi_power_off_full(struct omap_dss_device *dssdev) 234 { 235 struct omap_overlay_manager *mgr = hdmi.output.manager; 236 237 hdmi_wp_clear_irqenable(&hdmi.wp, 0xffffffff); 238 239 dss_mgr_disable(mgr); 240 241 hdmi_wp_video_stop(&hdmi.wp); 242 243 hdmi_wp_set_phy_pwr(&hdmi.wp, HDMI_PHYPWRCMD_OFF); 244 245 dss_pll_disable(&hdmi.pll.pll); 246 247 hdmi_power_off_core(dssdev); 248 } 249 250 static int hdmi_display_check_timing(struct omap_dss_device *dssdev, 251 struct omap_video_timings *timings) 252 { 253 struct omap_dss_device *out = &hdmi.output; 254 255 if (!dispc_mgr_timings_ok(out->dispc_channel, timings)) 256 return -EINVAL; 257 258 return 0; 259 } 260 261 static void hdmi_display_set_timing(struct omap_dss_device *dssdev, 262 struct omap_video_timings *timings) 263 { 264 mutex_lock(&hdmi.lock); 265 266 hdmi.cfg.timings = *timings; 267 268 dispc_set_tv_pclk(timings->pixelclock); 269 270 mutex_unlock(&hdmi.lock); 271 } 272 273 static void hdmi_display_get_timings(struct omap_dss_device *dssdev, 274 struct omap_video_timings *timings) 275 { 276 *timings = hdmi.cfg.timings; 277 } 278 279 static void hdmi_dump_regs(struct seq_file *s) 280 { 281 mutex_lock(&hdmi.lock); 282 283 if (hdmi_runtime_get()) { 284 mutex_unlock(&hdmi.lock); 285 return; 286 } 287 288 hdmi_wp_dump(&hdmi.wp, s); 289 hdmi_pll_dump(&hdmi.pll, s); 290 hdmi_phy_dump(&hdmi.phy, s); 291 hdmi4_core_dump(&hdmi.core, s); 292 293 hdmi_runtime_put(); 294 mutex_unlock(&hdmi.lock); 295 } 296 297 static int read_edid(u8 *buf, int len) 298 { 299 int r; 300 301 mutex_lock(&hdmi.lock); 302 303 r = hdmi_runtime_get(); 304 BUG_ON(r); 305 306 r = hdmi4_read_edid(&hdmi.core, buf, len); 307 308 hdmi_runtime_put(); 309 mutex_unlock(&hdmi.lock); 310 311 return r; 312 } 313 314 static void hdmi_start_audio_stream(struct omap_hdmi *hd) 315 { 316 hdmi_wp_audio_enable(&hd->wp, true); 317 hdmi4_audio_start(&hd->core, &hd->wp); 318 } 319 320 static void hdmi_stop_audio_stream(struct omap_hdmi *hd) 321 { 322 hdmi4_audio_stop(&hd->core, &hd->wp); 323 hdmi_wp_audio_enable(&hd->wp, false); 324 } 325 326 static int hdmi_display_enable(struct omap_dss_device *dssdev) 327 { 328 struct omap_dss_device *out = &hdmi.output; 329 unsigned long flags; 330 int r = 0; 331 332 DSSDBG("ENTER hdmi_display_enable\n"); 333 334 mutex_lock(&hdmi.lock); 335 336 if (out->manager == NULL) { 337 DSSERR("failed to enable display: no output/manager\n"); 338 r = -ENODEV; 339 goto err0; 340 } 341 342 r = hdmi_power_on_full(dssdev); 343 if (r) { 344 DSSERR("failed to power on device\n"); 345 goto err0; 346 } 347 348 if (hdmi.audio_configured) { 349 r = hdmi4_audio_config(&hdmi.core, &hdmi.wp, &hdmi.audio_config, 350 hdmi.cfg.timings.pixelclock); 351 if (r) { 352 DSSERR("Error restoring audio configuration: %d", r); 353 hdmi.audio_abort_cb(&hdmi.pdev->dev); 354 hdmi.audio_configured = false; 355 } 356 } 357 358 spin_lock_irqsave(&hdmi.audio_playing_lock, flags); 359 if (hdmi.audio_configured && hdmi.audio_playing) 360 hdmi_start_audio_stream(&hdmi); 361 hdmi.display_enabled = true; 362 spin_unlock_irqrestore(&hdmi.audio_playing_lock, flags); 363 364 mutex_unlock(&hdmi.lock); 365 return 0; 366 367 err0: 368 mutex_unlock(&hdmi.lock); 369 return r; 370 } 371 372 static void hdmi_display_disable(struct omap_dss_device *dssdev) 373 { 374 unsigned long flags; 375 376 DSSDBG("Enter hdmi_display_disable\n"); 377 378 mutex_lock(&hdmi.lock); 379 380 spin_lock_irqsave(&hdmi.audio_playing_lock, flags); 381 hdmi_stop_audio_stream(&hdmi); 382 hdmi.display_enabled = false; 383 spin_unlock_irqrestore(&hdmi.audio_playing_lock, flags); 384 385 hdmi_power_off_full(dssdev); 386 387 mutex_unlock(&hdmi.lock); 388 } 389 390 static int hdmi_core_enable(struct omap_dss_device *dssdev) 391 { 392 int r = 0; 393 394 DSSDBG("ENTER omapdss_hdmi_core_enable\n"); 395 396 mutex_lock(&hdmi.lock); 397 398 r = hdmi_power_on_core(dssdev); 399 if (r) { 400 DSSERR("failed to power on device\n"); 401 goto err0; 402 } 403 404 mutex_unlock(&hdmi.lock); 405 return 0; 406 407 err0: 408 mutex_unlock(&hdmi.lock); 409 return r; 410 } 411 412 static void hdmi_core_disable(struct omap_dss_device *dssdev) 413 { 414 DSSDBG("Enter omapdss_hdmi_core_disable\n"); 415 416 mutex_lock(&hdmi.lock); 417 418 hdmi_power_off_core(dssdev); 419 420 mutex_unlock(&hdmi.lock); 421 } 422 423 static int hdmi_connect(struct omap_dss_device *dssdev, 424 struct omap_dss_device *dst) 425 { 426 struct omap_overlay_manager *mgr; 427 int r; 428 429 r = hdmi_init_regulator(); 430 if (r) 431 return r; 432 433 mgr = omap_dss_get_overlay_manager(dssdev->dispc_channel); 434 if (!mgr) 435 return -ENODEV; 436 437 r = dss_mgr_connect(mgr, dssdev); 438 if (r) 439 return r; 440 441 r = omapdss_output_set_device(dssdev, dst); 442 if (r) { 443 DSSERR("failed to connect output to new device: %s\n", 444 dst->name); 445 dss_mgr_disconnect(mgr, dssdev); 446 return r; 447 } 448 449 return 0; 450 } 451 452 static void hdmi_disconnect(struct omap_dss_device *dssdev, 453 struct omap_dss_device *dst) 454 { 455 WARN_ON(dst != dssdev->dst); 456 457 if (dst != dssdev->dst) 458 return; 459 460 omapdss_output_unset_device(dssdev); 461 462 if (dssdev->manager) 463 dss_mgr_disconnect(dssdev->manager, dssdev); 464 } 465 466 static int hdmi_read_edid(struct omap_dss_device *dssdev, 467 u8 *edid, int len) 468 { 469 bool need_enable; 470 int r; 471 472 need_enable = hdmi.core_enabled == false; 473 474 if (need_enable) { 475 r = hdmi_core_enable(dssdev); 476 if (r) 477 return r; 478 } 479 480 r = read_edid(edid, len); 481 482 if (need_enable) 483 hdmi_core_disable(dssdev); 484 485 return r; 486 } 487 488 static int hdmi_set_infoframe(struct omap_dss_device *dssdev, 489 const struct hdmi_avi_infoframe *avi) 490 { 491 hdmi.cfg.infoframe = *avi; 492 return 0; 493 } 494 495 static int hdmi_set_hdmi_mode(struct omap_dss_device *dssdev, 496 bool hdmi_mode) 497 { 498 hdmi.cfg.hdmi_dvi_mode = hdmi_mode ? HDMI_HDMI : HDMI_DVI; 499 return 0; 500 } 501 502 static const struct omapdss_hdmi_ops hdmi_ops = { 503 .connect = hdmi_connect, 504 .disconnect = hdmi_disconnect, 505 506 .enable = hdmi_display_enable, 507 .disable = hdmi_display_disable, 508 509 .check_timings = hdmi_display_check_timing, 510 .set_timings = hdmi_display_set_timing, 511 .get_timings = hdmi_display_get_timings, 512 513 .read_edid = hdmi_read_edid, 514 .set_infoframe = hdmi_set_infoframe, 515 .set_hdmi_mode = hdmi_set_hdmi_mode, 516 }; 517 518 static void hdmi_init_output(struct platform_device *pdev) 519 { 520 struct omap_dss_device *out = &hdmi.output; 521 522 out->dev = &pdev->dev; 523 out->id = OMAP_DSS_OUTPUT_HDMI; 524 out->output_type = OMAP_DISPLAY_TYPE_HDMI; 525 out->name = "hdmi.0"; 526 out->dispc_channel = OMAP_DSS_CHANNEL_DIGIT; 527 out->ops.hdmi = &hdmi_ops; 528 out->owner = THIS_MODULE; 529 530 omapdss_register_output(out); 531 } 532 533 static void hdmi_uninit_output(struct platform_device *pdev) 534 { 535 struct omap_dss_device *out = &hdmi.output; 536 537 omapdss_unregister_output(out); 538 } 539 540 static int hdmi_probe_of(struct platform_device *pdev) 541 { 542 struct device_node *node = pdev->dev.of_node; 543 struct device_node *ep; 544 int r; 545 546 ep = omapdss_of_get_first_endpoint(node); 547 if (!ep) 548 return 0; 549 550 r = hdmi_parse_lanes_of(pdev, ep, &hdmi.phy); 551 if (r) 552 goto err; 553 554 of_node_put(ep); 555 return 0; 556 557 err: 558 of_node_put(ep); 559 return r; 560 } 561 562 /* Audio callbacks */ 563 static int hdmi_audio_startup(struct device *dev, 564 void (*abort_cb)(struct device *dev)) 565 { 566 struct omap_hdmi *hd = dev_get_drvdata(dev); 567 int ret = 0; 568 569 mutex_lock(&hd->lock); 570 571 if (!hdmi_mode_has_audio(&hd->cfg) || !hd->display_enabled) { 572 ret = -EPERM; 573 goto out; 574 } 575 576 hd->audio_abort_cb = abort_cb; 577 578 out: 579 mutex_unlock(&hd->lock); 580 581 return ret; 582 } 583 584 static int hdmi_audio_shutdown(struct device *dev) 585 { 586 struct omap_hdmi *hd = dev_get_drvdata(dev); 587 588 mutex_lock(&hd->lock); 589 hd->audio_abort_cb = NULL; 590 hd->audio_configured = false; 591 hd->audio_playing = false; 592 mutex_unlock(&hd->lock); 593 594 return 0; 595 } 596 597 static int hdmi_audio_start(struct device *dev) 598 { 599 struct omap_hdmi *hd = dev_get_drvdata(dev); 600 unsigned long flags; 601 602 WARN_ON(!hdmi_mode_has_audio(&hd->cfg)); 603 604 spin_lock_irqsave(&hd->audio_playing_lock, flags); 605 606 if (hd->display_enabled) 607 hdmi_start_audio_stream(hd); 608 hd->audio_playing = true; 609 610 spin_unlock_irqrestore(&hd->audio_playing_lock, flags); 611 return 0; 612 } 613 614 static void hdmi_audio_stop(struct device *dev) 615 { 616 struct omap_hdmi *hd = dev_get_drvdata(dev); 617 unsigned long flags; 618 619 WARN_ON(!hdmi_mode_has_audio(&hd->cfg)); 620 621 spin_lock_irqsave(&hd->audio_playing_lock, flags); 622 623 if (hd->display_enabled) 624 hdmi_stop_audio_stream(hd); 625 hd->audio_playing = false; 626 627 spin_unlock_irqrestore(&hd->audio_playing_lock, flags); 628 } 629 630 static int hdmi_audio_config(struct device *dev, 631 struct omap_dss_audio *dss_audio) 632 { 633 struct omap_hdmi *hd = dev_get_drvdata(dev); 634 int ret; 635 636 mutex_lock(&hd->lock); 637 638 if (!hdmi_mode_has_audio(&hd->cfg) || !hd->display_enabled) { 639 ret = -EPERM; 640 goto out; 641 } 642 643 ret = hdmi4_audio_config(&hd->core, &hd->wp, dss_audio, 644 hd->cfg.timings.pixelclock); 645 if (!ret) { 646 hd->audio_configured = true; 647 hd->audio_config = *dss_audio; 648 } 649 out: 650 mutex_unlock(&hd->lock); 651 652 return ret; 653 } 654 655 static const struct omap_hdmi_audio_ops hdmi_audio_ops = { 656 .audio_startup = hdmi_audio_startup, 657 .audio_shutdown = hdmi_audio_shutdown, 658 .audio_start = hdmi_audio_start, 659 .audio_stop = hdmi_audio_stop, 660 .audio_config = hdmi_audio_config, 661 }; 662 663 static int hdmi_audio_register(struct device *dev) 664 { 665 struct omap_hdmi_audio_pdata pdata = { 666 .dev = dev, 667 .dss_version = omapdss_get_version(), 668 .audio_dma_addr = hdmi_wp_get_audio_dma_addr(&hdmi.wp), 669 .ops = &hdmi_audio_ops, 670 }; 671 672 hdmi.audio_pdev = platform_device_register_data( 673 dev, "omap-hdmi-audio", PLATFORM_DEVID_AUTO, 674 &pdata, sizeof(pdata)); 675 676 if (IS_ERR(hdmi.audio_pdev)) 677 return PTR_ERR(hdmi.audio_pdev); 678 679 return 0; 680 } 681 682 /* HDMI HW IP initialisation */ 683 static int hdmi4_bind(struct device *dev, struct device *master, void *data) 684 { 685 struct platform_device *pdev = to_platform_device(dev); 686 int r; 687 int irq; 688 689 hdmi.pdev = pdev; 690 dev_set_drvdata(&pdev->dev, &hdmi); 691 692 mutex_init(&hdmi.lock); 693 spin_lock_init(&hdmi.audio_playing_lock); 694 695 if (pdev->dev.of_node) { 696 r = hdmi_probe_of(pdev); 697 if (r) 698 return r; 699 } 700 701 r = hdmi_wp_init(pdev, &hdmi.wp); 702 if (r) 703 return r; 704 705 r = hdmi_pll_init(pdev, &hdmi.pll, &hdmi.wp); 706 if (r) 707 return r; 708 709 r = hdmi_phy_init(pdev, &hdmi.phy); 710 if (r) 711 goto err; 712 713 r = hdmi4_core_init(pdev, &hdmi.core); 714 if (r) 715 goto err; 716 717 irq = platform_get_irq(pdev, 0); 718 if (irq < 0) { 719 DSSERR("platform_get_irq failed\n"); 720 r = -ENODEV; 721 goto err; 722 } 723 724 r = devm_request_threaded_irq(&pdev->dev, irq, 725 NULL, hdmi_irq_handler, 726 IRQF_ONESHOT, "OMAP HDMI", &hdmi.wp); 727 if (r) { 728 DSSERR("HDMI IRQ request failed\n"); 729 goto err; 730 } 731 732 pm_runtime_enable(&pdev->dev); 733 734 hdmi_init_output(pdev); 735 736 r = hdmi_audio_register(&pdev->dev); 737 if (r) { 738 DSSERR("Registering HDMI audio failed\n"); 739 hdmi_uninit_output(pdev); 740 pm_runtime_disable(&pdev->dev); 741 return r; 742 } 743 744 dss_debugfs_create_file("hdmi", hdmi_dump_regs); 745 746 return 0; 747 err: 748 hdmi_pll_uninit(&hdmi.pll); 749 return r; 750 } 751 752 static void hdmi4_unbind(struct device *dev, struct device *master, void *data) 753 { 754 struct platform_device *pdev = to_platform_device(dev); 755 756 if (hdmi.audio_pdev) 757 platform_device_unregister(hdmi.audio_pdev); 758 759 hdmi_uninit_output(pdev); 760 761 hdmi_pll_uninit(&hdmi.pll); 762 763 pm_runtime_disable(&pdev->dev); 764 } 765 766 static const struct component_ops hdmi4_component_ops = { 767 .bind = hdmi4_bind, 768 .unbind = hdmi4_unbind, 769 }; 770 771 static int hdmi4_probe(struct platform_device *pdev) 772 { 773 return component_add(&pdev->dev, &hdmi4_component_ops); 774 } 775 776 static int hdmi4_remove(struct platform_device *pdev) 777 { 778 component_del(&pdev->dev, &hdmi4_component_ops); 779 return 0; 780 } 781 782 static int hdmi_runtime_suspend(struct device *dev) 783 { 784 dispc_runtime_put(); 785 786 return 0; 787 } 788 789 static int hdmi_runtime_resume(struct device *dev) 790 { 791 int r; 792 793 r = dispc_runtime_get(); 794 if (r < 0) 795 return r; 796 797 return 0; 798 } 799 800 static const struct dev_pm_ops hdmi_pm_ops = { 801 .runtime_suspend = hdmi_runtime_suspend, 802 .runtime_resume = hdmi_runtime_resume, 803 }; 804 805 static const struct of_device_id hdmi_of_match[] = { 806 { .compatible = "ti,omap4-hdmi", }, 807 {}, 808 }; 809 810 static struct platform_driver omapdss_hdmihw_driver = { 811 .probe = hdmi4_probe, 812 .remove = hdmi4_remove, 813 .driver = { 814 .name = "omapdss_hdmi", 815 .pm = &hdmi_pm_ops, 816 .of_match_table = hdmi_of_match, 817 .suppress_bind_attrs = true, 818 }, 819 }; 820 821 int __init hdmi4_init_platform_driver(void) 822 { 823 return platform_driver_register(&omapdss_hdmihw_driver); 824 } 825 826 void hdmi4_uninit_platform_driver(void) 827 { 828 platform_driver_unregister(&omapdss_hdmihw_driver); 829 } 830