Back to home page

OSCL-LXR

 
 

    


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