root/drivers/video/fbdev/omap2/omapfb/dss/hdmi5.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. hdmi5_bind
  35. hdmi5_unbind
  36. hdmi5_probe
  37. hdmi5_remove
  38. hdmi_runtime_suspend
  39. hdmi_runtime_resume
  40. hdmi5_init_platform_driver
  41. hdmi5_uninit_platform_driver

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

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