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