0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
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
0077
0078
0079
0080
0081
0082 hdmi_wp_set_phy_pwr(wp, HDMI_PHYPWRCMD_OFF);
0083
0084
0085
0086
0087
0088
0089 v = hdmi_read_reg(hdmi.phy.base, HDMI_TXPHY_PAD_CFG_CTRL);
0090 v = FLD_MOD(v, 1, 15, 15);
0091 v = FLD_MOD(v, 0, 14, 7);
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
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
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
0209 dispc_enable_gamma_table(0);
0210
0211
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
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
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
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
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 }