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