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 37 static struct omap_hdmi hdmi; 38 39 static 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 54 static 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 64 static 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 110 static 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 128 static 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 147 err_runtime_get: 148 regulator_disable(hdmi.vdda_reg); 149 150 return r; 151 } 152 153 static 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 161 static 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 227 err_mgr_enable: 228 hdmi_wp_video_stop(&hdmi.wp); 229 err_vid_enable: 230 hdmi_wp_set_phy_pwr(&hdmi.wp, HDMI_PHYPWRCMD_OFF); 231 err_phy_pwr: 232 err_phy_cfg: 233 err_pll_cfg: 234 dss_pll_disable(&hdmi.pll.pll); 235 err_pll_enable: 236 hdmi_power_off_core(dssdev); 237 return -EIO; 238 } 239 240 static 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 257 static 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 272 static 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 284 static void hdmi_display_get_timings(struct omap_dss_device *dssdev, 285 struct omap_video_timings *timings) 286 { 287 *timings = hdmi.cfg.timings; 288 } 289 290 static 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 308 static 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 332 static 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 339 static 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 346 static 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 387 err0: 388 mutex_unlock(&hdmi.lock); 389 return r; 390 } 391 392 static 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 410 static 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 427 err0: 428 mutex_unlock(&hdmi.lock); 429 return r; 430 } 431 432 static 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 443 static 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 472 static 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 486 static 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 508 static 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 515 static 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 522 static 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 538 static 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 553 static 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 560 static 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 577 err: 578 of_node_put(ep); 579 return r; 580 } 581 582 /* Audio callbacks */ 583 static 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 598 out: 599 mutex_unlock(&hd->lock); 600 601 return ret; 602 } 603 604 static 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 617 static 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 634 static 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 650 static 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 } 670 out: 671 mutex_unlock(&hd->lock); 672 673 return ret; 674 } 675 676 static 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 684 static 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 */ 709 static 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; 773 err: 774 hdmi_pll_uninit(&hdmi.pll); 775 return r; 776 } 777 778 static 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 792 static const struct component_ops hdmi5_component_ops = { 793 .bind = hdmi5_bind, 794 .unbind = hdmi5_unbind, 795 }; 796 797 static int hdmi5_probe(struct platform_device *pdev) 798 { 799 return component_add(&pdev->dev, &hdmi5_component_ops); 800 } 801 802 static int hdmi5_remove(struct platform_device *pdev) 803 { 804 component_del(&pdev->dev, &hdmi5_component_ops); 805 return 0; 806 } 807 808 static int hdmi_runtime_suspend(struct device *dev) 809 { 810 dispc_runtime_put(); 811 812 return 0; 813 } 814 815 static 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 826 static const struct dev_pm_ops hdmi_pm_ops = { 827 .runtime_suspend = hdmi_runtime_suspend, 828 .runtime_resume = hdmi_runtime_resume, 829 }; 830 831 static const struct of_device_id hdmi_of_match[] = { 832 { .compatible = "ti,omap5-hdmi", }, 833 { .compatible = "ti,dra7-hdmi", }, 834 {}, 835 }; 836 837 static 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 848 int __init hdmi5_init_platform_driver(void) 849 { 850 return platform_driver_register(&omapdss_hdmihw_driver); 851 } 852 853 void hdmi5_uninit_platform_driver(void) 854 { 855 platform_driver_unregister(&omapdss_hdmihw_driver); 856 } 857