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