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