0001
0002
0003
0004
0005
0006
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
0072
0073
0074
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
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
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
0192 dispc_enable_gamma_table(0);
0193
0194
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
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
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 }