1 // SPDX-License-Identifier: GPL-2.0-only 2 /* 3 * HDMI driver for OMAP5 4 * 5 * Copyright (C) 2014 Texas Instruments Incorporated - http://www.ti.com/ 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/gpio.h> 28 #include <linux/regulator/consumer.h> 29 #include <linux/component.h> 30 #include <linux/of.h> 31 #include <linux/of_graph.h> 32 #include <sound/omap-hdmi-audio.h> 33 34 #include <drm/drm_atomic.h> 35 #include <drm/drm_atomic_state_helper.h> 36 37 #include "omapdss.h" 38 #include "hdmi5_core.h" 39 #include "dss.h" 40 41 static int hdmi_runtime_get(struct omap_hdmi *hdmi) 42 { 43 int r; 44 45 DSSDBG("hdmi_runtime_get\n"); 46 47 r = pm_runtime_get_sync(&hdmi->pdev->dev); 48 WARN_ON(r < 0); 49 if (r < 0) 50 return r; 51 52 return 0; 53 } 54 55 static void hdmi_runtime_put(struct omap_hdmi *hdmi) 56 { 57 int r; 58 59 DSSDBG("hdmi_runtime_put\n"); 60 61 r = pm_runtime_put_sync(&hdmi->pdev->dev); 62 WARN_ON(r < 0 && r != -ENOSYS); 63 } 64 65 static irqreturn_t hdmi_irq_handler(int irq, void *data) 66 { 67 struct omap_hdmi *hdmi = data; 68 struct hdmi_wp_data *wp = &hdmi->wp; 69 u32 irqstatus; 70 71 irqstatus = hdmi_wp_get_irqstatus(wp); 72 hdmi_wp_set_irqstatus(wp, irqstatus); 73 74 if ((irqstatus & HDMI_IRQ_LINK_CONNECT) && 75 irqstatus & HDMI_IRQ_LINK_DISCONNECT) { 76 u32 v; 77 /* 78 * If we get both connect and disconnect interrupts at the same 79 * time, turn off the PHY, clear interrupts, and restart, which 80 * raises connect interrupt if a cable is connected, or nothing 81 * if cable is not connected. 82 */ 83 84 hdmi_wp_set_phy_pwr(wp, HDMI_PHYPWRCMD_OFF); 85 86 /* 87 * We always get bogus CONNECT & DISCONNECT interrupts when 88 * setting the PHY to LDOON. To ignore those, we force the RXDET 89 * line to 0 until the PHY power state has been changed. 90 */ 91 v = hdmi_read_reg(hdmi->phy.base, HDMI_TXPHY_PAD_CFG_CTRL); 92 v = FLD_MOD(v, 1, 15, 15); /* FORCE_RXDET_HIGH */ 93 v = FLD_MOD(v, 0, 14, 7); /* RXDET_LINE */ 94 hdmi_write_reg(hdmi->phy.base, HDMI_TXPHY_PAD_CFG_CTRL, v); 95 96 hdmi_wp_set_irqstatus(wp, HDMI_IRQ_LINK_CONNECT | 97 HDMI_IRQ_LINK_DISCONNECT); 98 99 hdmi_wp_set_phy_pwr(wp, HDMI_PHYPWRCMD_LDOON); 100 101 REG_FLD_MOD(hdmi->phy.base, HDMI_TXPHY_PAD_CFG_CTRL, 0, 15, 15); 102 103 } else if (irqstatus & HDMI_IRQ_LINK_CONNECT) { 104 hdmi_wp_set_phy_pwr(wp, HDMI_PHYPWRCMD_TXON); 105 } else if (irqstatus & HDMI_IRQ_LINK_DISCONNECT) { 106 hdmi_wp_set_phy_pwr(wp, HDMI_PHYPWRCMD_LDOON); 107 } 108 109 return IRQ_HANDLED; 110 } 111 112 static int hdmi_power_on_core(struct omap_hdmi *hdmi) 113 { 114 int r; 115 116 r = regulator_enable(hdmi->vdda_reg); 117 if (r) 118 return r; 119 120 r = hdmi_runtime_get(hdmi); 121 if (r) 122 goto err_runtime_get; 123 124 /* Make selection of HDMI in DSS */ 125 dss_select_hdmi_venc_clk_source(hdmi->dss, DSS_HDMI_M_PCLK); 126 127 hdmi->core_enabled = true; 128 129 return 0; 130 131 err_runtime_get: 132 regulator_disable(hdmi->vdda_reg); 133 134 return r; 135 } 136 137 static void hdmi_power_off_core(struct omap_hdmi *hdmi) 138 { 139 hdmi->core_enabled = false; 140 141 hdmi_runtime_put(hdmi); 142 regulator_disable(hdmi->vdda_reg); 143 } 144 145 static int hdmi_power_on_full(struct omap_hdmi *hdmi) 146 { 147 int r; 148 const struct videomode *vm; 149 struct dss_pll_clock_info hdmi_cinfo = { 0 }; 150 unsigned int pc; 151 152 r = hdmi_power_on_core(hdmi); 153 if (r) 154 return r; 155 156 vm = &hdmi->cfg.vm; 157 158 DSSDBG("hdmi_power_on hactive= %d vactive = %d\n", vm->hactive, 159 vm->vactive); 160 161 pc = vm->pixelclock; 162 if (vm->flags & DISPLAY_FLAGS_DOUBLECLK) 163 pc *= 2; 164 165 /* DSS_HDMI_TCLK is bitclk / 10 */ 166 pc *= 10; 167 168 dss_pll_calc_b(&hdmi->pll.pll, clk_get_rate(hdmi->pll.pll.clkin), 169 pc, &hdmi_cinfo); 170 171 /* disable and clear irqs */ 172 hdmi_wp_clear_irqenable(&hdmi->wp, 0xffffffff); 173 hdmi_wp_set_irqstatus(&hdmi->wp, 174 hdmi_wp_get_irqstatus(&hdmi->wp)); 175 176 r = dss_pll_enable(&hdmi->pll.pll); 177 if (r) { 178 DSSERR("Failed to enable PLL\n"); 179 goto err_pll_enable; 180 } 181 182 r = dss_pll_set_config(&hdmi->pll.pll, &hdmi_cinfo); 183 if (r) { 184 DSSERR("Failed to configure PLL\n"); 185 goto err_pll_cfg; 186 } 187 188 r = hdmi_phy_configure(&hdmi->phy, hdmi_cinfo.clkdco, 189 hdmi_cinfo.clkout[0]); 190 if (r) { 191 DSSDBG("Failed to start PHY\n"); 192 goto err_phy_cfg; 193 } 194 195 r = hdmi_wp_set_phy_pwr(&hdmi->wp, HDMI_PHYPWRCMD_LDOON); 196 if (r) 197 goto err_phy_pwr; 198 199 hdmi5_configure(&hdmi->core, &hdmi->wp, &hdmi->cfg); 200 201 r = dss_mgr_enable(&hdmi->output); 202 if (r) 203 goto err_mgr_enable; 204 205 r = hdmi_wp_video_start(&hdmi->wp); 206 if (r) 207 goto err_vid_enable; 208 209 hdmi_wp_set_irqenable(&hdmi->wp, 210 HDMI_IRQ_LINK_CONNECT | HDMI_IRQ_LINK_DISCONNECT); 211 212 return 0; 213 214 err_vid_enable: 215 dss_mgr_disable(&hdmi->output); 216 err_mgr_enable: 217 hdmi_wp_set_phy_pwr(&hdmi->wp, HDMI_PHYPWRCMD_OFF); 218 err_phy_pwr: 219 err_phy_cfg: 220 err_pll_cfg: 221 dss_pll_disable(&hdmi->pll.pll); 222 err_pll_enable: 223 hdmi_power_off_core(hdmi); 224 return -EIO; 225 } 226 227 static void hdmi_power_off_full(struct omap_hdmi *hdmi) 228 { 229 hdmi_wp_clear_irqenable(&hdmi->wp, 0xffffffff); 230 231 hdmi_wp_video_stop(&hdmi->wp); 232 233 dss_mgr_disable(&hdmi->output); 234 235 hdmi_wp_set_phy_pwr(&hdmi->wp, HDMI_PHYPWRCMD_OFF); 236 237 dss_pll_disable(&hdmi->pll.pll); 238 239 hdmi_power_off_core(hdmi); 240 } 241 242 static int hdmi_dump_regs(struct seq_file *s, void *p) 243 { 244 struct omap_hdmi *hdmi = s->private; 245 246 mutex_lock(&hdmi->lock); 247 248 if (hdmi_runtime_get(hdmi)) { 249 mutex_unlock(&hdmi->lock); 250 return 0; 251 } 252 253 hdmi_wp_dump(&hdmi->wp, s); 254 hdmi_pll_dump(&hdmi->pll, s); 255 hdmi_phy_dump(&hdmi->phy, s); 256 hdmi5_core_dump(&hdmi->core, s); 257 258 hdmi_runtime_put(hdmi); 259 mutex_unlock(&hdmi->lock); 260 return 0; 261 } 262 263 static void hdmi_start_audio_stream(struct omap_hdmi *hd) 264 { 265 REG_FLD_MOD(hd->wp.base, HDMI_WP_SYSCONFIG, 1, 3, 2); 266 hdmi_wp_audio_enable(&hd->wp, true); 267 hdmi_wp_audio_core_req_enable(&hd->wp, true); 268 } 269 270 static void hdmi_stop_audio_stream(struct omap_hdmi *hd) 271 { 272 hdmi_wp_audio_core_req_enable(&hd->wp, false); 273 hdmi_wp_audio_enable(&hd->wp, false); 274 REG_FLD_MOD(hd->wp.base, HDMI_WP_SYSCONFIG, hd->wp_idlemode, 3, 2); 275 } 276 277 static int hdmi_core_enable(struct omap_hdmi *hdmi) 278 { 279 int r = 0; 280 281 DSSDBG("ENTER omapdss_hdmi_core_enable\n"); 282 283 mutex_lock(&hdmi->lock); 284 285 r = hdmi_power_on_core(hdmi); 286 if (r) { 287 DSSERR("failed to power on device\n"); 288 goto err0; 289 } 290 291 mutex_unlock(&hdmi->lock); 292 return 0; 293 294 err0: 295 mutex_unlock(&hdmi->lock); 296 return r; 297 } 298 299 static void hdmi_core_disable(struct omap_hdmi *hdmi) 300 { 301 DSSDBG("Enter omapdss_hdmi_core_disable\n"); 302 303 mutex_lock(&hdmi->lock); 304 305 hdmi_power_off_core(hdmi); 306 307 mutex_unlock(&hdmi->lock); 308 } 309 310 static int hdmi_connect(struct omap_dss_device *src, 311 struct omap_dss_device *dst) 312 { 313 return omapdss_device_connect(dst->dss, dst, dst->next); 314 } 315 316 static void hdmi_disconnect(struct omap_dss_device *src, 317 struct omap_dss_device *dst) 318 { 319 omapdss_device_disconnect(dst, dst->next); 320 } 321 322 #define MAX_EDID 512 323 324 static struct edid *hdmi_read_edid_data(struct omap_hdmi *hdmi, 325 struct drm_connector *connector) 326 { 327 struct hdmi_core_data *core = &hdmi->core; 328 int max_ext_blocks = 3; 329 int r, n, i; 330 u8 *edid; 331 332 edid = kzalloc(MAX_EDID, GFP_KERNEL); 333 if (!edid) 334 return NULL; 335 336 r = hdmi5_core_ddc_read(core, edid, 0, EDID_LENGTH); 337 if (r) 338 goto error; 339 340 n = edid[0x7e]; 341 342 if (n > max_ext_blocks) 343 n = max_ext_blocks; 344 345 for (i = 1; i <= n; i++) { 346 r = hdmi5_core_ddc_read(core, edid + i * EDID_LENGTH, i, 347 EDID_LENGTH); 348 if (r) 349 goto error; 350 } 351 352 return (struct edid *)edid; 353 354 error: 355 kfree(edid); 356 return NULL; 357 } 358 359 static struct edid * 360 hdmi_do_read_edid(struct omap_hdmi *hdmi, 361 struct edid *(*read)(struct omap_hdmi *hdmi, 362 struct drm_connector *connector), 363 struct drm_connector *connector) 364 { 365 struct edid *edid; 366 bool need_enable; 367 int idlemode; 368 int r; 369 370 need_enable = hdmi->core_enabled == false; 371 372 if (need_enable) { 373 r = hdmi_core_enable(hdmi); 374 if (r) 375 return NULL; 376 } 377 378 mutex_lock(&hdmi->lock); 379 r = hdmi_runtime_get(hdmi); 380 BUG_ON(r); 381 382 idlemode = REG_GET(hdmi->wp.base, HDMI_WP_SYSCONFIG, 3, 2); 383 /* No-idle mode */ 384 REG_FLD_MOD(hdmi->wp.base, HDMI_WP_SYSCONFIG, 1, 3, 2); 385 386 hdmi5_core_ddc_init(&hdmi->core); 387 388 edid = read(hdmi, connector); 389 390 hdmi5_core_ddc_uninit(&hdmi->core); 391 392 REG_FLD_MOD(hdmi->wp.base, HDMI_WP_SYSCONFIG, idlemode, 3, 2); 393 394 hdmi_runtime_put(hdmi); 395 mutex_unlock(&hdmi->lock); 396 397 if (need_enable) 398 hdmi_core_disable(hdmi); 399 400 return (struct edid *)edid; 401 } 402 403 static struct edid *hdmi_read_edid(struct omap_dss_device *dssdev) 404 { 405 return hdmi_do_read_edid(dssdev_to_hdmi(dssdev), hdmi_read_edid_data, 406 NULL); 407 } 408 409 static const struct omap_dss_device_ops hdmi_ops = { 410 .connect = hdmi_connect, 411 .disconnect = hdmi_disconnect, 412 413 .read_edid = hdmi_read_edid, 414 }; 415 416 /* ----------------------------------------------------------------------------- 417 * DRM Bridge Operations 418 */ 419 420 static int hdmi5_bridge_attach(struct drm_bridge *bridge, 421 enum drm_bridge_attach_flags flags) 422 { 423 struct omap_hdmi *hdmi = drm_bridge_to_hdmi(bridge); 424 425 if (!(flags & DRM_BRIDGE_ATTACH_NO_CONNECTOR)) 426 return -EINVAL; 427 428 return drm_bridge_attach(bridge->encoder, hdmi->output.next_bridge, 429 bridge, flags); 430 } 431 432 static void hdmi5_bridge_mode_set(struct drm_bridge *bridge, 433 const struct drm_display_mode *mode, 434 const struct drm_display_mode *adjusted_mode) 435 { 436 struct omap_hdmi *hdmi = drm_bridge_to_hdmi(bridge); 437 438 mutex_lock(&hdmi->lock); 439 440 drm_display_mode_to_videomode(adjusted_mode, &hdmi->cfg.vm); 441 442 dispc_set_tv_pclk(hdmi->dss->dispc, adjusted_mode->clock * 1000); 443 444 mutex_unlock(&hdmi->lock); 445 } 446 447 static void hdmi5_bridge_enable(struct drm_bridge *bridge, 448 struct drm_bridge_state *bridge_state) 449 { 450 struct omap_hdmi *hdmi = drm_bridge_to_hdmi(bridge); 451 struct drm_atomic_state *state = bridge_state->base.state; 452 struct drm_connector_state *conn_state; 453 struct drm_connector *connector; 454 struct drm_crtc_state *crtc_state; 455 unsigned long flags; 456 int ret; 457 458 /* 459 * None of these should fail, as the bridge can't be enabled without a 460 * valid CRTC to connector path with fully populated new states. 461 */ 462 connector = drm_atomic_get_new_connector_for_encoder(state, 463 bridge->encoder); 464 if (WARN_ON(!connector)) 465 return; 466 conn_state = drm_atomic_get_new_connector_state(state, connector); 467 if (WARN_ON(!conn_state)) 468 return; 469 crtc_state = drm_atomic_get_new_crtc_state(state, conn_state->crtc); 470 if (WARN_ON(!crtc_state)) 471 return; 472 473 hdmi->cfg.hdmi_dvi_mode = connector->display_info.is_hdmi 474 ? HDMI_HDMI : HDMI_DVI; 475 476 if (connector->display_info.is_hdmi) { 477 const struct drm_display_mode *mode; 478 struct hdmi_avi_infoframe avi; 479 480 mode = &crtc_state->adjusted_mode; 481 ret = drm_hdmi_avi_infoframe_from_display_mode(&avi, connector, 482 mode); 483 if (ret == 0) 484 hdmi->cfg.infoframe = avi; 485 } 486 487 mutex_lock(&hdmi->lock); 488 489 ret = hdmi_power_on_full(hdmi); 490 if (ret) { 491 DSSERR("failed to power on device\n"); 492 goto done; 493 } 494 495 if (hdmi->audio_configured) { 496 ret = hdmi5_audio_config(&hdmi->core, &hdmi->wp, 497 &hdmi->audio_config, 498 hdmi->cfg.vm.pixelclock); 499 if (ret) { 500 DSSERR("Error restoring audio configuration: %d", ret); 501 hdmi->audio_abort_cb(&hdmi->pdev->dev); 502 hdmi->audio_configured = false; 503 } 504 } 505 506 spin_lock_irqsave(&hdmi->audio_playing_lock, flags); 507 if (hdmi->audio_configured && hdmi->audio_playing) 508 hdmi_start_audio_stream(hdmi); 509 hdmi->display_enabled = true; 510 spin_unlock_irqrestore(&hdmi->audio_playing_lock, flags); 511 512 done: 513 mutex_unlock(&hdmi->lock); 514 } 515 516 static void hdmi5_bridge_disable(struct drm_bridge *bridge, 517 struct drm_bridge_state *bridge_state) 518 { 519 struct omap_hdmi *hdmi = drm_bridge_to_hdmi(bridge); 520 unsigned long flags; 521 522 mutex_lock(&hdmi->lock); 523 524 spin_lock_irqsave(&hdmi->audio_playing_lock, flags); 525 hdmi_stop_audio_stream(hdmi); 526 hdmi->display_enabled = false; 527 spin_unlock_irqrestore(&hdmi->audio_playing_lock, flags); 528 529 hdmi_power_off_full(hdmi); 530 531 mutex_unlock(&hdmi->lock); 532 } 533 534 static struct edid *hdmi5_bridge_read_edid(struct omap_hdmi *hdmi, 535 struct drm_connector *connector) 536 { 537 return drm_do_get_edid(connector, hdmi5_core_ddc_read, &hdmi->core); 538 } 539 540 static struct edid *hdmi5_bridge_get_edid(struct drm_bridge *bridge, 541 struct drm_connector *connector) 542 { 543 struct omap_hdmi *hdmi = drm_bridge_to_hdmi(bridge); 544 545 return hdmi_do_read_edid(hdmi, hdmi5_bridge_read_edid, connector); 546 } 547 548 static const struct drm_bridge_funcs hdmi5_bridge_funcs = { 549 .attach = hdmi5_bridge_attach, 550 .mode_set = hdmi5_bridge_mode_set, 551 .atomic_duplicate_state = drm_atomic_helper_bridge_duplicate_state, 552 .atomic_destroy_state = drm_atomic_helper_bridge_destroy_state, 553 .atomic_reset = drm_atomic_helper_bridge_reset, 554 .atomic_enable = hdmi5_bridge_enable, 555 .atomic_disable = hdmi5_bridge_disable, 556 .get_edid = hdmi5_bridge_get_edid, 557 }; 558 559 static void hdmi5_bridge_init(struct omap_hdmi *hdmi) 560 { 561 hdmi->bridge.funcs = &hdmi5_bridge_funcs; 562 hdmi->bridge.of_node = hdmi->pdev->dev.of_node; 563 hdmi->bridge.ops = DRM_BRIDGE_OP_EDID; 564 hdmi->bridge.type = DRM_MODE_CONNECTOR_HDMIA; 565 566 drm_bridge_add(&hdmi->bridge); 567 } 568 569 static void hdmi5_bridge_cleanup(struct omap_hdmi *hdmi) 570 { 571 drm_bridge_remove(&hdmi->bridge); 572 } 573 574 /* ----------------------------------------------------------------------------- 575 * Audio Callbacks 576 */ 577 578 static int hdmi_audio_startup(struct device *dev, 579 void (*abort_cb)(struct device *dev)) 580 { 581 struct omap_hdmi *hd = dev_get_drvdata(dev); 582 583 mutex_lock(&hd->lock); 584 585 WARN_ON(hd->audio_abort_cb != NULL); 586 587 hd->audio_abort_cb = abort_cb; 588 589 mutex_unlock(&hd->lock); 590 591 return 0; 592 } 593 594 static int hdmi_audio_shutdown(struct device *dev) 595 { 596 struct omap_hdmi *hd = dev_get_drvdata(dev); 597 598 mutex_lock(&hd->lock); 599 hd->audio_abort_cb = NULL; 600 hd->audio_configured = false; 601 hd->audio_playing = false; 602 mutex_unlock(&hd->lock); 603 604 return 0; 605 } 606 607 static int hdmi_audio_start(struct device *dev) 608 { 609 struct omap_hdmi *hd = dev_get_drvdata(dev); 610 unsigned long flags; 611 612 spin_lock_irqsave(&hd->audio_playing_lock, flags); 613 614 if (hd->display_enabled) { 615 if (!hdmi_mode_has_audio(&hd->cfg)) 616 DSSERR("%s: Video mode does not support audio\n", 617 __func__); 618 hdmi_start_audio_stream(hd); 619 } 620 hd->audio_playing = true; 621 622 spin_unlock_irqrestore(&hd->audio_playing_lock, flags); 623 return 0; 624 } 625 626 static void hdmi_audio_stop(struct device *dev) 627 { 628 struct omap_hdmi *hd = dev_get_drvdata(dev); 629 unsigned long flags; 630 631 if (!hdmi_mode_has_audio(&hd->cfg)) 632 DSSERR("%s: Video mode does not support audio\n", __func__); 633 634 spin_lock_irqsave(&hd->audio_playing_lock, flags); 635 636 if (hd->display_enabled) 637 hdmi_stop_audio_stream(hd); 638 hd->audio_playing = false; 639 640 spin_unlock_irqrestore(&hd->audio_playing_lock, flags); 641 } 642 643 static int hdmi_audio_config(struct device *dev, 644 struct omap_dss_audio *dss_audio) 645 { 646 struct omap_hdmi *hd = dev_get_drvdata(dev); 647 int ret = 0; 648 649 mutex_lock(&hd->lock); 650 651 if (hd->display_enabled) { 652 ret = hdmi5_audio_config(&hd->core, &hd->wp, dss_audio, 653 hd->cfg.vm.pixelclock); 654 if (ret) 655 goto out; 656 } 657 658 hd->audio_configured = true; 659 hd->audio_config = *dss_audio; 660 out: 661 mutex_unlock(&hd->lock); 662 663 return ret; 664 } 665 666 static const struct omap_hdmi_audio_ops hdmi_audio_ops = { 667 .audio_startup = hdmi_audio_startup, 668 .audio_shutdown = hdmi_audio_shutdown, 669 .audio_start = hdmi_audio_start, 670 .audio_stop = hdmi_audio_stop, 671 .audio_config = hdmi_audio_config, 672 }; 673 674 static int hdmi_audio_register(struct omap_hdmi *hdmi) 675 { 676 struct omap_hdmi_audio_pdata pdata = { 677 .dev = &hdmi->pdev->dev, 678 .version = 5, 679 .audio_dma_addr = hdmi_wp_get_audio_dma_addr(&hdmi->wp), 680 .ops = &hdmi_audio_ops, 681 }; 682 683 hdmi->audio_pdev = platform_device_register_data( 684 &hdmi->pdev->dev, "omap-hdmi-audio", PLATFORM_DEVID_AUTO, 685 &pdata, sizeof(pdata)); 686 687 if (IS_ERR(hdmi->audio_pdev)) 688 return PTR_ERR(hdmi->audio_pdev); 689 690 hdmi_runtime_get(hdmi); 691 hdmi->wp_idlemode = 692 REG_GET(hdmi->wp.base, HDMI_WP_SYSCONFIG, 3, 2); 693 hdmi_runtime_put(hdmi); 694 695 return 0; 696 } 697 698 /* ----------------------------------------------------------------------------- 699 * Component Bind & Unbind 700 */ 701 702 static int hdmi5_bind(struct device *dev, struct device *master, void *data) 703 { 704 struct dss_device *dss = dss_get_device(master); 705 struct omap_hdmi *hdmi = dev_get_drvdata(dev); 706 int r; 707 708 hdmi->dss = dss; 709 710 r = hdmi_pll_init(dss, hdmi->pdev, &hdmi->pll, &hdmi->wp); 711 if (r) 712 return r; 713 714 r = hdmi_audio_register(hdmi); 715 if (r) { 716 DSSERR("Registering HDMI audio failed %d\n", r); 717 goto err_pll_uninit; 718 } 719 720 hdmi->debugfs = dss_debugfs_create_file(dss, "hdmi", hdmi_dump_regs, 721 hdmi); 722 723 return 0; 724 725 err_pll_uninit: 726 hdmi_pll_uninit(&hdmi->pll); 727 return r; 728 } 729 730 static void hdmi5_unbind(struct device *dev, struct device *master, void *data) 731 { 732 struct omap_hdmi *hdmi = dev_get_drvdata(dev); 733 734 dss_debugfs_remove_file(hdmi->debugfs); 735 736 if (hdmi->audio_pdev) 737 platform_device_unregister(hdmi->audio_pdev); 738 739 hdmi_pll_uninit(&hdmi->pll); 740 } 741 742 static const struct component_ops hdmi5_component_ops = { 743 .bind = hdmi5_bind, 744 .unbind = hdmi5_unbind, 745 }; 746 747 /* ----------------------------------------------------------------------------- 748 * Probe & Remove, Suspend & Resume 749 */ 750 751 static int hdmi5_init_output(struct omap_hdmi *hdmi) 752 { 753 struct omap_dss_device *out = &hdmi->output; 754 int r; 755 756 hdmi5_bridge_init(hdmi); 757 758 out->dev = &hdmi->pdev->dev; 759 out->id = OMAP_DSS_OUTPUT_HDMI; 760 out->type = OMAP_DISPLAY_TYPE_HDMI; 761 out->name = "hdmi.0"; 762 out->dispc_channel = OMAP_DSS_CHANNEL_DIGIT; 763 out->ops = &hdmi_ops; 764 out->owner = THIS_MODULE; 765 out->of_port = 0; 766 out->ops_flags = OMAP_DSS_DEVICE_OP_EDID; 767 768 r = omapdss_device_init_output(out, &hdmi->bridge); 769 if (r < 0) { 770 hdmi5_bridge_cleanup(hdmi); 771 return r; 772 } 773 774 omapdss_device_register(out); 775 776 return 0; 777 } 778 779 static void hdmi5_uninit_output(struct omap_hdmi *hdmi) 780 { 781 struct omap_dss_device *out = &hdmi->output; 782 783 omapdss_device_unregister(out); 784 omapdss_device_cleanup_output(out); 785 786 hdmi5_bridge_cleanup(hdmi); 787 } 788 789 static int hdmi5_probe_of(struct omap_hdmi *hdmi) 790 { 791 struct platform_device *pdev = hdmi->pdev; 792 struct device_node *node = pdev->dev.of_node; 793 struct device_node *ep; 794 int r; 795 796 ep = of_graph_get_endpoint_by_regs(node, 0, 0); 797 if (!ep) 798 return 0; 799 800 r = hdmi_parse_lanes_of(pdev, ep, &hdmi->phy); 801 of_node_put(ep); 802 return r; 803 } 804 805 static int hdmi5_probe(struct platform_device *pdev) 806 { 807 struct omap_hdmi *hdmi; 808 int irq; 809 int r; 810 811 hdmi = kzalloc(sizeof(*hdmi), GFP_KERNEL); 812 if (!hdmi) 813 return -ENOMEM; 814 815 hdmi->pdev = pdev; 816 817 dev_set_drvdata(&pdev->dev, hdmi); 818 819 mutex_init(&hdmi->lock); 820 spin_lock_init(&hdmi->audio_playing_lock); 821 822 r = hdmi5_probe_of(hdmi); 823 if (r) 824 goto err_free; 825 826 r = hdmi_wp_init(pdev, &hdmi->wp, 5); 827 if (r) 828 goto err_free; 829 830 r = hdmi_phy_init(pdev, &hdmi->phy, 5); 831 if (r) 832 goto err_free; 833 834 r = hdmi5_core_init(pdev, &hdmi->core); 835 if (r) 836 goto err_free; 837 838 irq = platform_get_irq(pdev, 0); 839 if (irq < 0) { 840 DSSERR("platform_get_irq failed\n"); 841 r = -ENODEV; 842 goto err_free; 843 } 844 845 r = devm_request_threaded_irq(&pdev->dev, irq, 846 NULL, hdmi_irq_handler, 847 IRQF_ONESHOT, "OMAP HDMI", hdmi); 848 if (r) { 849 DSSERR("HDMI IRQ request failed\n"); 850 goto err_free; 851 } 852 853 hdmi->vdda_reg = devm_regulator_get(&pdev->dev, "vdda"); 854 if (IS_ERR(hdmi->vdda_reg)) { 855 r = PTR_ERR(hdmi->vdda_reg); 856 if (r != -EPROBE_DEFER) 857 DSSERR("can't get VDDA regulator\n"); 858 goto err_free; 859 } 860 861 pm_runtime_enable(&pdev->dev); 862 863 r = hdmi5_init_output(hdmi); 864 if (r) 865 goto err_pm_disable; 866 867 r = component_add(&pdev->dev, &hdmi5_component_ops); 868 if (r) 869 goto err_uninit_output; 870 871 return 0; 872 873 err_uninit_output: 874 hdmi5_uninit_output(hdmi); 875 err_pm_disable: 876 pm_runtime_disable(&pdev->dev); 877 err_free: 878 kfree(hdmi); 879 return r; 880 } 881 882 static int hdmi5_remove(struct platform_device *pdev) 883 { 884 struct omap_hdmi *hdmi = platform_get_drvdata(pdev); 885 886 component_del(&pdev->dev, &hdmi5_component_ops); 887 888 hdmi5_uninit_output(hdmi); 889 890 pm_runtime_disable(&pdev->dev); 891 892 kfree(hdmi); 893 return 0; 894 } 895 896 static const struct of_device_id hdmi_of_match[] = { 897 { .compatible = "ti,omap5-hdmi", }, 898 { .compatible = "ti,dra7-hdmi", }, 899 {}, 900 }; 901 902 struct platform_driver omapdss_hdmi5hw_driver = { 903 .probe = hdmi5_probe, 904 .remove = hdmi5_remove, 905 .driver = { 906 .name = "omapdss_hdmi5", 907 .of_match_table = hdmi_of_match, 908 .suppress_bind_attrs = true, 909 }, 910 }; 911