root/drivers/video/fbdev/omap2/omapfb/dss/hdmi4.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. hdmi_runtime_get
  2. hdmi_runtime_put
  3. hdmi_irq_handler
  4. hdmi_init_regulator
  5. hdmi_power_on_core
  6. hdmi_power_off_core
  7. hdmi_power_on_full
  8. hdmi_power_off_full
  9. hdmi_display_check_timing
  10. hdmi_display_set_timing
  11. hdmi_display_get_timings
  12. hdmi_dump_regs
  13. read_edid
  14. hdmi_start_audio_stream
  15. hdmi_stop_audio_stream
  16. hdmi_display_enable
  17. hdmi_display_disable
  18. hdmi_core_enable
  19. hdmi_core_disable
  20. hdmi_connect
  21. hdmi_disconnect
  22. hdmi_read_edid
  23. hdmi_set_infoframe
  24. hdmi_set_hdmi_mode
  25. hdmi_init_output
  26. hdmi_uninit_output
  27. hdmi_probe_of
  28. hdmi_audio_startup
  29. hdmi_audio_shutdown
  30. hdmi_audio_start
  31. hdmi_audio_stop
  32. hdmi_audio_config
  33. hdmi_audio_register
  34. hdmi4_bind
  35. hdmi4_unbind
  36. hdmi4_probe
  37. hdmi4_remove
  38. hdmi_runtime_suspend
  39. hdmi_runtime_resume
  40. hdmi4_init_platform_driver
  41. hdmi4_uninit_platform_driver

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

/* [<][>][^][v][top][bottom][index][help] */