Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0-only
0002 /*
0003  * HDMI driver for OMAP5
0004  *
0005  * Copyright (C) 2014 Texas Instruments Incorporated
0006  *
0007  * Authors:
0008  *  Yong Zhi
0009  *  Mythri pk
0010  *  Archit Taneja <archit@ti.com>
0011  *  Tomi Valkeinen <tomi.valkeinen@ti.com>
0012  */
0013 
0014 #define DSS_SUBSYS_NAME "HDMI"
0015 
0016 #include <linux/kernel.h>
0017 #include <linux/module.h>
0018 #include <linux/err.h>
0019 #include <linux/io.h>
0020 #include <linux/interrupt.h>
0021 #include <linux/mutex.h>
0022 #include <linux/delay.h>
0023 #include <linux/string.h>
0024 #include <linux/platform_device.h>
0025 #include <linux/pm_runtime.h>
0026 #include <linux/clk.h>
0027 #include <linux/of.h>
0028 #include <linux/regulator/consumer.h>
0029 #include <linux/component.h>
0030 #include <video/omapfb_dss.h>
0031 #include <sound/omap-hdmi-audio.h>
0032 
0033 #include "hdmi5_core.h"
0034 #include "dss.h"
0035 #include "dss_features.h"
0036 
0037 static struct omap_hdmi hdmi;
0038 
0039 static int hdmi_runtime_get(void)
0040 {
0041     int r;
0042 
0043     DSSDBG("hdmi_runtime_get\n");
0044 
0045     r = pm_runtime_get_sync(&hdmi.pdev->dev);
0046     if (WARN_ON(r < 0)) {
0047         pm_runtime_put_sync(&hdmi.pdev->dev);
0048         return r;
0049     }
0050 
0051     return 0;
0052 }
0053 
0054 static void hdmi_runtime_put(void)
0055 {
0056     int r;
0057 
0058     DSSDBG("hdmi_runtime_put\n");
0059 
0060     r = pm_runtime_put_sync(&hdmi.pdev->dev);
0061     WARN_ON(r < 0 && r != -ENOSYS);
0062 }
0063 
0064 static irqreturn_t hdmi_irq_handler(int irq, void *data)
0065 {
0066     struct hdmi_wp_data *wp = data;
0067     u32 irqstatus;
0068 
0069     irqstatus = hdmi_wp_get_irqstatus(wp);
0070     hdmi_wp_set_irqstatus(wp, irqstatus);
0071 
0072     if ((irqstatus & HDMI_IRQ_LINK_CONNECT) &&
0073             irqstatus & HDMI_IRQ_LINK_DISCONNECT) {
0074         u32 v;
0075         /*
0076          * If we get both connect and disconnect interrupts at the same
0077          * time, turn off the PHY, clear interrupts, and restart, which
0078          * raises connect interrupt if a cable is connected, or nothing
0079          * if cable is not connected.
0080          */
0081 
0082         hdmi_wp_set_phy_pwr(wp, HDMI_PHYPWRCMD_OFF);
0083 
0084         /*
0085          * We always get bogus CONNECT & DISCONNECT interrupts when
0086          * setting the PHY to LDOON. To ignore those, we force the RXDET
0087          * line to 0 until the PHY power state has been changed.
0088          */
0089         v = hdmi_read_reg(hdmi.phy.base, HDMI_TXPHY_PAD_CFG_CTRL);
0090         v = FLD_MOD(v, 1, 15, 15); /* FORCE_RXDET_HIGH */
0091         v = FLD_MOD(v, 0, 14, 7); /* RXDET_LINE */
0092         hdmi_write_reg(hdmi.phy.base, HDMI_TXPHY_PAD_CFG_CTRL, v);
0093 
0094         hdmi_wp_set_irqstatus(wp, HDMI_IRQ_LINK_CONNECT |
0095                 HDMI_IRQ_LINK_DISCONNECT);
0096 
0097         hdmi_wp_set_phy_pwr(wp, HDMI_PHYPWRCMD_LDOON);
0098 
0099         REG_FLD_MOD(hdmi.phy.base, HDMI_TXPHY_PAD_CFG_CTRL, 0, 15, 15);
0100 
0101     } else if (irqstatus & HDMI_IRQ_LINK_CONNECT) {
0102         hdmi_wp_set_phy_pwr(wp, HDMI_PHYPWRCMD_TXON);
0103     } else if (irqstatus & HDMI_IRQ_LINK_DISCONNECT) {
0104         hdmi_wp_set_phy_pwr(wp, HDMI_PHYPWRCMD_LDOON);
0105     }
0106 
0107     return IRQ_HANDLED;
0108 }
0109 
0110 static int hdmi_init_regulator(void)
0111 {
0112     struct regulator *reg;
0113 
0114     if (hdmi.vdda_reg != NULL)
0115         return 0;
0116 
0117     reg = devm_regulator_get(&hdmi.pdev->dev, "vdda");
0118     if (IS_ERR(reg)) {
0119         DSSERR("can't get VDDA regulator\n");
0120         return PTR_ERR(reg);
0121     }
0122 
0123     hdmi.vdda_reg = reg;
0124 
0125     return 0;
0126 }
0127 
0128 static int hdmi_power_on_core(struct omap_dss_device *dssdev)
0129 {
0130     int r;
0131 
0132     r = regulator_enable(hdmi.vdda_reg);
0133     if (r)
0134         return r;
0135 
0136     r = hdmi_runtime_get();
0137     if (r)
0138         goto err_runtime_get;
0139 
0140     /* Make selection of HDMI in DSS */
0141     dss_select_hdmi_venc_clk_source(DSS_HDMI_M_PCLK);
0142 
0143     hdmi.core_enabled = true;
0144 
0145     return 0;
0146 
0147 err_runtime_get:
0148     regulator_disable(hdmi.vdda_reg);
0149 
0150     return r;
0151 }
0152 
0153 static void hdmi_power_off_core(struct omap_dss_device *dssdev)
0154 {
0155     hdmi.core_enabled = false;
0156 
0157     hdmi_runtime_put();
0158     regulator_disable(hdmi.vdda_reg);
0159 }
0160 
0161 static int hdmi_power_on_full(struct omap_dss_device *dssdev)
0162 {
0163     int r;
0164     struct omap_video_timings *p;
0165     struct omap_overlay_manager *mgr = hdmi.output.manager;
0166     struct dss_pll_clock_info hdmi_cinfo = { 0 };
0167 
0168     r = hdmi_power_on_core(dssdev);
0169     if (r)
0170         return r;
0171 
0172     p = &hdmi.cfg.timings;
0173 
0174     DSSDBG("hdmi_power_on x_res= %d y_res = %d\n", p->x_res, p->y_res);
0175 
0176     hdmi_pll_compute(&hdmi.pll, p->pixelclock, &hdmi_cinfo);
0177 
0178     /* disable and clear irqs */
0179     hdmi_wp_clear_irqenable(&hdmi.wp, 0xffffffff);
0180     hdmi_wp_set_irqstatus(&hdmi.wp,
0181             hdmi_wp_get_irqstatus(&hdmi.wp));
0182 
0183     r = dss_pll_enable(&hdmi.pll.pll);
0184     if (r) {
0185         DSSERR("Failed to enable PLL\n");
0186         goto err_pll_enable;
0187     }
0188 
0189     r = dss_pll_set_config(&hdmi.pll.pll, &hdmi_cinfo);
0190     if (r) {
0191         DSSERR("Failed to configure PLL\n");
0192         goto err_pll_cfg;
0193     }
0194 
0195     r = hdmi_phy_configure(&hdmi.phy, hdmi_cinfo.clkdco,
0196         hdmi_cinfo.clkout[0]);
0197     if (r) {
0198         DSSDBG("Failed to start PHY\n");
0199         goto err_phy_cfg;
0200     }
0201 
0202     r = hdmi_wp_set_phy_pwr(&hdmi.wp, HDMI_PHYPWRCMD_LDOON);
0203     if (r)
0204         goto err_phy_pwr;
0205 
0206     hdmi5_configure(&hdmi.core, &hdmi.wp, &hdmi.cfg);
0207 
0208     /* bypass TV gamma table */
0209     dispc_enable_gamma_table(0);
0210 
0211     /* tv size */
0212     dss_mgr_set_timings(mgr, p);
0213 
0214     r = hdmi_wp_video_start(&hdmi.wp);
0215     if (r)
0216         goto err_vid_enable;
0217 
0218     r = dss_mgr_enable(mgr);
0219     if (r)
0220         goto err_mgr_enable;
0221 
0222     hdmi_wp_set_irqenable(&hdmi.wp,
0223             HDMI_IRQ_LINK_CONNECT | HDMI_IRQ_LINK_DISCONNECT);
0224 
0225     return 0;
0226 
0227 err_mgr_enable:
0228     hdmi_wp_video_stop(&hdmi.wp);
0229 err_vid_enable:
0230     hdmi_wp_set_phy_pwr(&hdmi.wp, HDMI_PHYPWRCMD_OFF);
0231 err_phy_pwr:
0232 err_phy_cfg:
0233 err_pll_cfg:
0234     dss_pll_disable(&hdmi.pll.pll);
0235 err_pll_enable:
0236     hdmi_power_off_core(dssdev);
0237     return -EIO;
0238 }
0239 
0240 static void hdmi_power_off_full(struct omap_dss_device *dssdev)
0241 {
0242     struct omap_overlay_manager *mgr = hdmi.output.manager;
0243 
0244     hdmi_wp_clear_irqenable(&hdmi.wp, 0xffffffff);
0245 
0246     dss_mgr_disable(mgr);
0247 
0248     hdmi_wp_video_stop(&hdmi.wp);
0249 
0250     hdmi_wp_set_phy_pwr(&hdmi.wp, HDMI_PHYPWRCMD_OFF);
0251 
0252     dss_pll_disable(&hdmi.pll.pll);
0253 
0254     hdmi_power_off_core(dssdev);
0255 }
0256 
0257 static int hdmi_display_check_timing(struct omap_dss_device *dssdev,
0258                     struct omap_video_timings *timings)
0259 {
0260     struct omap_dss_device *out = &hdmi.output;
0261 
0262     /* TODO: proper interlace support */
0263     if (timings->interlace)
0264         return -EINVAL;
0265 
0266     if (!dispc_mgr_timings_ok(out->dispc_channel, timings))
0267         return -EINVAL;
0268 
0269     return 0;
0270 }
0271 
0272 static void hdmi_display_set_timing(struct omap_dss_device *dssdev,
0273         struct omap_video_timings *timings)
0274 {
0275     mutex_lock(&hdmi.lock);
0276 
0277     hdmi.cfg.timings = *timings;
0278 
0279     dispc_set_tv_pclk(timings->pixelclock);
0280 
0281     mutex_unlock(&hdmi.lock);
0282 }
0283 
0284 static void hdmi_display_get_timings(struct omap_dss_device *dssdev,
0285         struct omap_video_timings *timings)
0286 {
0287     *timings = hdmi.cfg.timings;
0288 }
0289 
0290 static void hdmi_dump_regs(struct seq_file *s)
0291 {
0292     mutex_lock(&hdmi.lock);
0293 
0294     if (hdmi_runtime_get()) {
0295         mutex_unlock(&hdmi.lock);
0296         return;
0297     }
0298 
0299     hdmi_wp_dump(&hdmi.wp, s);
0300     hdmi_pll_dump(&hdmi.pll, s);
0301     hdmi_phy_dump(&hdmi.phy, s);
0302     hdmi5_core_dump(&hdmi.core, s);
0303 
0304     hdmi_runtime_put();
0305     mutex_unlock(&hdmi.lock);
0306 }
0307 
0308 static int read_edid(u8 *buf, int len)
0309 {
0310     int r;
0311     int idlemode;
0312 
0313     mutex_lock(&hdmi.lock);
0314 
0315     r = hdmi_runtime_get();
0316     BUG_ON(r);
0317 
0318     idlemode = REG_GET(hdmi.wp.base, HDMI_WP_SYSCONFIG, 3, 2);
0319     /* No-idle mode */
0320     REG_FLD_MOD(hdmi.wp.base, HDMI_WP_SYSCONFIG, 1, 3, 2);
0321 
0322     r = hdmi5_read_edid(&hdmi.core,  buf, len);
0323 
0324     REG_FLD_MOD(hdmi.wp.base, HDMI_WP_SYSCONFIG, idlemode, 3, 2);
0325 
0326     hdmi_runtime_put();
0327     mutex_unlock(&hdmi.lock);
0328 
0329     return r;
0330 }
0331 
0332 static void hdmi_start_audio_stream(struct omap_hdmi *hd)
0333 {
0334     REG_FLD_MOD(hdmi.wp.base, HDMI_WP_SYSCONFIG, 1, 3, 2);
0335     hdmi_wp_audio_enable(&hd->wp, true);
0336     hdmi_wp_audio_core_req_enable(&hd->wp, true);
0337 }
0338 
0339 static void hdmi_stop_audio_stream(struct omap_hdmi *hd)
0340 {
0341     hdmi_wp_audio_core_req_enable(&hd->wp, false);
0342     hdmi_wp_audio_enable(&hd->wp, false);
0343     REG_FLD_MOD(hd->wp.base, HDMI_WP_SYSCONFIG, hd->wp_idlemode, 3, 2);
0344 }
0345 
0346 static int hdmi_display_enable(struct omap_dss_device *dssdev)
0347 {
0348     struct omap_dss_device *out = &hdmi.output;
0349     unsigned long flags;
0350     int r = 0;
0351 
0352     DSSDBG("ENTER hdmi_display_enable\n");
0353 
0354     mutex_lock(&hdmi.lock);
0355 
0356     if (out->manager == NULL) {
0357         DSSERR("failed to enable display: no output/manager\n");
0358         r = -ENODEV;
0359         goto err0;
0360     }
0361 
0362     r = hdmi_power_on_full(dssdev);
0363     if (r) {
0364         DSSERR("failed to power on device\n");
0365         goto err0;
0366     }
0367 
0368     if (hdmi.audio_configured) {
0369         r = hdmi5_audio_config(&hdmi.core, &hdmi.wp, &hdmi.audio_config,
0370                        hdmi.cfg.timings.pixelclock);
0371         if (r) {
0372             DSSERR("Error restoring audio configuration: %d", r);
0373             hdmi.audio_abort_cb(&hdmi.pdev->dev);
0374             hdmi.audio_configured = false;
0375         }
0376     }
0377 
0378     spin_lock_irqsave(&hdmi.audio_playing_lock, flags);
0379     if (hdmi.audio_configured && hdmi.audio_playing)
0380         hdmi_start_audio_stream(&hdmi);
0381     hdmi.display_enabled = true;
0382     spin_unlock_irqrestore(&hdmi.audio_playing_lock, flags);
0383 
0384     mutex_unlock(&hdmi.lock);
0385     return 0;
0386 
0387 err0:
0388     mutex_unlock(&hdmi.lock);
0389     return r;
0390 }
0391 
0392 static void hdmi_display_disable(struct omap_dss_device *dssdev)
0393 {
0394     unsigned long flags;
0395 
0396     DSSDBG("Enter hdmi_display_disable\n");
0397 
0398     mutex_lock(&hdmi.lock);
0399 
0400     spin_lock_irqsave(&hdmi.audio_playing_lock, flags);
0401     hdmi_stop_audio_stream(&hdmi);
0402     hdmi.display_enabled = false;
0403     spin_unlock_irqrestore(&hdmi.audio_playing_lock, flags);
0404 
0405     hdmi_power_off_full(dssdev);
0406 
0407     mutex_unlock(&hdmi.lock);
0408 }
0409 
0410 static int hdmi_core_enable(struct omap_dss_device *dssdev)
0411 {
0412     int r = 0;
0413 
0414     DSSDBG("ENTER omapdss_hdmi_core_enable\n");
0415 
0416     mutex_lock(&hdmi.lock);
0417 
0418     r = hdmi_power_on_core(dssdev);
0419     if (r) {
0420         DSSERR("failed to power on device\n");
0421         goto err0;
0422     }
0423 
0424     mutex_unlock(&hdmi.lock);
0425     return 0;
0426 
0427 err0:
0428     mutex_unlock(&hdmi.lock);
0429     return r;
0430 }
0431 
0432 static void hdmi_core_disable(struct omap_dss_device *dssdev)
0433 {
0434     DSSDBG("Enter omapdss_hdmi_core_disable\n");
0435 
0436     mutex_lock(&hdmi.lock);
0437 
0438     hdmi_power_off_core(dssdev);
0439 
0440     mutex_unlock(&hdmi.lock);
0441 }
0442 
0443 static int hdmi_connect(struct omap_dss_device *dssdev,
0444         struct omap_dss_device *dst)
0445 {
0446     struct omap_overlay_manager *mgr;
0447     int r;
0448 
0449     r = hdmi_init_regulator();
0450     if (r)
0451         return r;
0452 
0453     mgr = omap_dss_get_overlay_manager(dssdev->dispc_channel);
0454     if (!mgr)
0455         return -ENODEV;
0456 
0457     r = dss_mgr_connect(mgr, dssdev);
0458     if (r)
0459         return r;
0460 
0461     r = omapdss_output_set_device(dssdev, dst);
0462     if (r) {
0463         DSSERR("failed to connect output to new device: %s\n",
0464                 dst->name);
0465         dss_mgr_disconnect(mgr, dssdev);
0466         return r;
0467     }
0468 
0469     return 0;
0470 }
0471 
0472 static void hdmi_disconnect(struct omap_dss_device *dssdev,
0473         struct omap_dss_device *dst)
0474 {
0475     WARN_ON(dst != dssdev->dst);
0476 
0477     if (dst != dssdev->dst)
0478         return;
0479 
0480     omapdss_output_unset_device(dssdev);
0481 
0482     if (dssdev->manager)
0483         dss_mgr_disconnect(dssdev->manager, dssdev);
0484 }
0485 
0486 static int hdmi_read_edid(struct omap_dss_device *dssdev,
0487         u8 *edid, int len)
0488 {
0489     bool need_enable;
0490     int r;
0491 
0492     need_enable = hdmi.core_enabled == false;
0493 
0494     if (need_enable) {
0495         r = hdmi_core_enable(dssdev);
0496         if (r)
0497             return r;
0498     }
0499 
0500     r = read_edid(edid, len);
0501 
0502     if (need_enable)
0503         hdmi_core_disable(dssdev);
0504 
0505     return r;
0506 }
0507 
0508 static int hdmi_set_infoframe(struct omap_dss_device *dssdev,
0509         const struct hdmi_avi_infoframe *avi)
0510 {
0511     hdmi.cfg.infoframe = *avi;
0512     return 0;
0513 }
0514 
0515 static int hdmi_set_hdmi_mode(struct omap_dss_device *dssdev,
0516         bool hdmi_mode)
0517 {
0518     hdmi.cfg.hdmi_dvi_mode = hdmi_mode ? HDMI_HDMI : HDMI_DVI;
0519     return 0;
0520 }
0521 
0522 static const struct omapdss_hdmi_ops hdmi_ops = {
0523     .connect        = hdmi_connect,
0524     .disconnect     = hdmi_disconnect,
0525 
0526     .enable         = hdmi_display_enable,
0527     .disable        = hdmi_display_disable,
0528 
0529     .check_timings      = hdmi_display_check_timing,
0530     .set_timings        = hdmi_display_set_timing,
0531     .get_timings        = hdmi_display_get_timings,
0532 
0533     .read_edid      = hdmi_read_edid,
0534     .set_infoframe      = hdmi_set_infoframe,
0535     .set_hdmi_mode      = hdmi_set_hdmi_mode,
0536 };
0537 
0538 static void hdmi_init_output(struct platform_device *pdev)
0539 {
0540     struct omap_dss_device *out = &hdmi.output;
0541 
0542     out->dev = &pdev->dev;
0543     out->id = OMAP_DSS_OUTPUT_HDMI;
0544     out->output_type = OMAP_DISPLAY_TYPE_HDMI;
0545     out->name = "hdmi.0";
0546     out->dispc_channel = OMAP_DSS_CHANNEL_DIGIT;
0547     out->ops.hdmi = &hdmi_ops;
0548     out->owner = THIS_MODULE;
0549 
0550     omapdss_register_output(out);
0551 }
0552 
0553 static void hdmi_uninit_output(struct platform_device *pdev)
0554 {
0555     struct omap_dss_device *out = &hdmi.output;
0556 
0557     omapdss_unregister_output(out);
0558 }
0559 
0560 static int hdmi_probe_of(struct platform_device *pdev)
0561 {
0562     struct device_node *node = pdev->dev.of_node;
0563     struct device_node *ep;
0564     int r;
0565 
0566     ep = omapdss_of_get_first_endpoint(node);
0567     if (!ep)
0568         return 0;
0569 
0570     r = hdmi_parse_lanes_of(pdev, ep, &hdmi.phy);
0571     if (r)
0572         goto err;
0573 
0574     of_node_put(ep);
0575     return 0;
0576 
0577 err:
0578     of_node_put(ep);
0579     return r;
0580 }
0581 
0582 /* Audio callbacks */
0583 static int hdmi_audio_startup(struct device *dev,
0584                   void (*abort_cb)(struct device *dev))
0585 {
0586     struct omap_hdmi *hd = dev_get_drvdata(dev);
0587     int ret = 0;
0588 
0589     mutex_lock(&hd->lock);
0590 
0591     if (!hdmi_mode_has_audio(&hd->cfg) || !hd->display_enabled) {
0592         ret = -EPERM;
0593         goto out;
0594     }
0595 
0596     hd->audio_abort_cb = abort_cb;
0597 
0598 out:
0599     mutex_unlock(&hd->lock);
0600 
0601     return ret;
0602 }
0603 
0604 static int hdmi_audio_shutdown(struct device *dev)
0605 {
0606     struct omap_hdmi *hd = dev_get_drvdata(dev);
0607 
0608     mutex_lock(&hd->lock);
0609     hd->audio_abort_cb = NULL;
0610     hd->audio_configured = false;
0611     hd->audio_playing = false;
0612     mutex_unlock(&hd->lock);
0613 
0614     return 0;
0615 }
0616 
0617 static int hdmi_audio_start(struct device *dev)
0618 {
0619     struct omap_hdmi *hd = dev_get_drvdata(dev);
0620     unsigned long flags;
0621 
0622     WARN_ON(!hdmi_mode_has_audio(&hd->cfg));
0623 
0624     spin_lock_irqsave(&hd->audio_playing_lock, flags);
0625 
0626     if (hd->display_enabled)
0627         hdmi_start_audio_stream(hd);
0628     hd->audio_playing = true;
0629 
0630     spin_unlock_irqrestore(&hd->audio_playing_lock, flags);
0631     return 0;
0632 }
0633 
0634 static void hdmi_audio_stop(struct device *dev)
0635 {
0636     struct omap_hdmi *hd = dev_get_drvdata(dev);
0637     unsigned long flags;
0638 
0639     WARN_ON(!hdmi_mode_has_audio(&hd->cfg));
0640 
0641     spin_lock_irqsave(&hd->audio_playing_lock, flags);
0642 
0643     if (hd->display_enabled)
0644         hdmi_stop_audio_stream(hd);
0645     hd->audio_playing = false;
0646 
0647     spin_unlock_irqrestore(&hd->audio_playing_lock, flags);
0648 }
0649 
0650 static int hdmi_audio_config(struct device *dev,
0651                  struct omap_dss_audio *dss_audio)
0652 {
0653     struct omap_hdmi *hd = dev_get_drvdata(dev);
0654     int ret;
0655 
0656     mutex_lock(&hd->lock);
0657 
0658     if (!hdmi_mode_has_audio(&hd->cfg) || !hd->display_enabled) {
0659         ret = -EPERM;
0660         goto out;
0661     }
0662 
0663     ret = hdmi5_audio_config(&hd->core, &hd->wp, dss_audio,
0664                  hd->cfg.timings.pixelclock);
0665 
0666     if (!ret) {
0667         hd->audio_configured = true;
0668         hd->audio_config = *dss_audio;
0669     }
0670 out:
0671     mutex_unlock(&hd->lock);
0672 
0673     return ret;
0674 }
0675 
0676 static const struct omap_hdmi_audio_ops hdmi_audio_ops = {
0677     .audio_startup = hdmi_audio_startup,
0678     .audio_shutdown = hdmi_audio_shutdown,
0679     .audio_start = hdmi_audio_start,
0680     .audio_stop = hdmi_audio_stop,
0681     .audio_config = hdmi_audio_config,
0682 };
0683 
0684 static int hdmi_audio_register(struct device *dev)
0685 {
0686     struct omap_hdmi_audio_pdata pdata = {
0687         .dev = dev,
0688         .version = 5,
0689         .audio_dma_addr = hdmi_wp_get_audio_dma_addr(&hdmi.wp),
0690         .ops = &hdmi_audio_ops,
0691     };
0692 
0693     hdmi.audio_pdev = platform_device_register_data(
0694         dev, "omap-hdmi-audio", PLATFORM_DEVID_AUTO,
0695         &pdata, sizeof(pdata));
0696 
0697     if (IS_ERR(hdmi.audio_pdev))
0698         return PTR_ERR(hdmi.audio_pdev);
0699 
0700     hdmi_runtime_get();
0701     hdmi.wp_idlemode =
0702         REG_GET(hdmi.wp.base, HDMI_WP_SYSCONFIG, 3, 2);
0703     hdmi_runtime_put();
0704 
0705     return 0;
0706 }
0707 
0708 /* HDMI HW IP initialisation */
0709 static int hdmi5_bind(struct device *dev, struct device *master, void *data)
0710 {
0711     struct platform_device *pdev = to_platform_device(dev);
0712     int r;
0713     int irq;
0714 
0715     hdmi.pdev = pdev;
0716     platform_set_drvdata(pdev, &hdmi);
0717 
0718     mutex_init(&hdmi.lock);
0719     spin_lock_init(&hdmi.audio_playing_lock);
0720 
0721     if (pdev->dev.of_node) {
0722         r = hdmi_probe_of(pdev);
0723         if (r)
0724             return r;
0725     }
0726 
0727     r = hdmi_wp_init(pdev, &hdmi.wp);
0728     if (r)
0729         return r;
0730 
0731     r = hdmi_pll_init(pdev, &hdmi.pll, &hdmi.wp);
0732     if (r)
0733         return r;
0734 
0735     r = hdmi_phy_init(pdev, &hdmi.phy);
0736     if (r)
0737         goto err;
0738 
0739     r = hdmi5_core_init(pdev, &hdmi.core);
0740     if (r)
0741         goto err;
0742 
0743     irq = platform_get_irq(pdev, 0);
0744     if (irq < 0) {
0745         DSSERR("platform_get_irq failed\n");
0746         r = -ENODEV;
0747         goto err;
0748     }
0749 
0750     r = devm_request_threaded_irq(&pdev->dev, irq,
0751             NULL, hdmi_irq_handler,
0752             IRQF_ONESHOT, "OMAP HDMI", &hdmi.wp);
0753     if (r) {
0754         DSSERR("HDMI IRQ request failed\n");
0755         goto err;
0756     }
0757 
0758     pm_runtime_enable(&pdev->dev);
0759 
0760     hdmi_init_output(pdev);
0761 
0762     r = hdmi_audio_register(&pdev->dev);
0763     if (r) {
0764         DSSERR("Registering HDMI audio failed %d\n", r);
0765         hdmi_uninit_output(pdev);
0766         pm_runtime_disable(&pdev->dev);
0767         return r;
0768     }
0769 
0770     dss_debugfs_create_file("hdmi", hdmi_dump_regs);
0771 
0772     return 0;
0773 err:
0774     hdmi_pll_uninit(&hdmi.pll);
0775     return r;
0776 }
0777 
0778 static void hdmi5_unbind(struct device *dev, struct device *master, void *data)
0779 {
0780     struct platform_device *pdev = to_platform_device(dev);
0781 
0782     if (hdmi.audio_pdev)
0783         platform_device_unregister(hdmi.audio_pdev);
0784 
0785     hdmi_uninit_output(pdev);
0786 
0787     hdmi_pll_uninit(&hdmi.pll);
0788 
0789     pm_runtime_disable(&pdev->dev);
0790 }
0791 
0792 static const struct component_ops hdmi5_component_ops = {
0793     .bind   = hdmi5_bind,
0794     .unbind = hdmi5_unbind,
0795 };
0796 
0797 static int hdmi5_probe(struct platform_device *pdev)
0798 {
0799     return component_add(&pdev->dev, &hdmi5_component_ops);
0800 }
0801 
0802 static int hdmi5_remove(struct platform_device *pdev)
0803 {
0804     component_del(&pdev->dev, &hdmi5_component_ops);
0805     return 0;
0806 }
0807 
0808 static int hdmi_runtime_suspend(struct device *dev)
0809 {
0810     dispc_runtime_put();
0811 
0812     return 0;
0813 }
0814 
0815 static int hdmi_runtime_resume(struct device *dev)
0816 {
0817     int r;
0818 
0819     r = dispc_runtime_get();
0820     if (r < 0)
0821         return r;
0822 
0823     return 0;
0824 }
0825 
0826 static const struct dev_pm_ops hdmi_pm_ops = {
0827     .runtime_suspend = hdmi_runtime_suspend,
0828     .runtime_resume = hdmi_runtime_resume,
0829 };
0830 
0831 static const struct of_device_id hdmi_of_match[] = {
0832     { .compatible = "ti,omap5-hdmi", },
0833     { .compatible = "ti,dra7-hdmi", },
0834     {},
0835 };
0836 
0837 static struct platform_driver omapdss_hdmihw_driver = {
0838     .probe      = hdmi5_probe,
0839     .remove     = hdmi5_remove,
0840     .driver         = {
0841         .name   = "omapdss_hdmi5",
0842         .pm = &hdmi_pm_ops,
0843         .of_match_table = hdmi_of_match,
0844         .suppress_bind_attrs = true,
0845     },
0846 };
0847 
0848 int __init hdmi5_init_platform_driver(void)
0849 {
0850     return platform_driver_register(&omapdss_hdmihw_driver);
0851 }
0852 
0853 void hdmi5_uninit_platform_driver(void)
0854 {
0855     platform_driver_unregister(&omapdss_hdmihw_driver);
0856 }