1 /*
2 * HDMI driver for OMAP5
3 *
4 * Copyright (C) 2014 Texas Instruments Incorporated
5 *
6 * Authors:
7 * Yong Zhi
8 * Mythri pk
9 * Archit Taneja <archit@ti.com>
10 * Tomi Valkeinen <tomi.valkeinen@ti.com>
11 *
12 * This program is free software; you can redistribute it and/or modify it
13 * under the terms of the GNU General Public License version 2 as published by
14 * the Free Software Foundation.
15 *
16 * This program is distributed in the hope that it will be useful, but WITHOUT
17 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
18 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
19 * more details.
20 *
21 * You should have received a copy of the GNU General Public License along with
22 * this program. If not, see <http://www.gnu.org/licenses/>.
23 */
25 #define DSS_SUBSYS_NAME "HDMI"
27 #include <linux/kernel.h>
28 #include <linux/module.h>
29 #include <linux/err.h>
30 #include <linux/io.h>
31 #include <linux/interrupt.h>
32 #include <linux/mutex.h>
33 #include <linux/delay.h>
34 #include <linux/string.h>
35 #include <linux/platform_device.h>
36 #include <linux/pm_runtime.h>
37 #include <linux/clk.h>
38 #include <linux/gpio.h>
39 #include <linux/regulator/consumer.h>
40 #include <video/omapdss.h>
41 #include <sound/omap-hdmi-audio.h>
43 #include "hdmi5_core.h"
44 #include "dss.h"
45 #include "dss_features.h"
47 static struct omap_hdmi hdmi;
49 static int hdmi_runtime_get(void)
50 {
51 int r;
53 DSSDBG("hdmi_runtime_get\n");
55 r = pm_runtime_get_sync(&hdmi.pdev->dev);
56 WARN_ON(r < 0);
57 if (r < 0)
58 return r;
60 return 0;
61 }
63 static void hdmi_runtime_put(void)
64 {
65 int r;
67 DSSDBG("hdmi_runtime_put\n");
69 r = pm_runtime_put_sync(&hdmi.pdev->dev);
70 WARN_ON(r < 0 && r != -ENOSYS);
71 }
73 static irqreturn_t hdmi_irq_handler(int irq, void *data)
74 {
75 struct hdmi_wp_data *wp = data;
76 u32 irqstatus;
78 irqstatus = hdmi_wp_get_irqstatus(wp);
79 hdmi_wp_set_irqstatus(wp, irqstatus);
81 if ((irqstatus & HDMI_IRQ_LINK_CONNECT) &&
82 irqstatus & HDMI_IRQ_LINK_DISCONNECT) {
83 u32 v;
84 /*
85 * If we get both connect and disconnect interrupts at the same
86 * time, turn off the PHY, clear interrupts, and restart, which
87 * raises connect interrupt if a cable is connected, or nothing
88 * if cable is not connected.
89 */
91 hdmi_wp_set_phy_pwr(wp, HDMI_PHYPWRCMD_OFF);
93 /*
94 * We always get bogus CONNECT & DISCONNECT interrupts when
95 * setting the PHY to LDOON. To ignore those, we force the RXDET
96 * line to 0 until the PHY power state has been changed.
97 */
98 v = hdmi_read_reg(hdmi.phy.base, HDMI_TXPHY_PAD_CFG_CTRL);
99 v = FLD_MOD(v, 1, 15, 15); /* FORCE_RXDET_HIGH */
100 v = FLD_MOD(v, 0, 14, 7); /* RXDET_LINE */
101 hdmi_write_reg(hdmi.phy.base, HDMI_TXPHY_PAD_CFG_CTRL, v);
103 hdmi_wp_set_irqstatus(wp, HDMI_IRQ_LINK_CONNECT |
104 HDMI_IRQ_LINK_DISCONNECT);
106 hdmi_wp_set_phy_pwr(wp, HDMI_PHYPWRCMD_LDOON);
108 REG_FLD_MOD(hdmi.phy.base, HDMI_TXPHY_PAD_CFG_CTRL, 0, 15, 15);
110 } else if (irqstatus & HDMI_IRQ_LINK_CONNECT) {
111 hdmi_wp_set_phy_pwr(wp, HDMI_PHYPWRCMD_TXON);
112 extcon_set_state(&hdmi.edev, 1);
113 } else if (irqstatus & HDMI_IRQ_LINK_DISCONNECT) {
114 hdmi_wp_set_phy_pwr(wp, HDMI_PHYPWRCMD_LDOON);
115 extcon_set_state(&hdmi.edev, 0);
116 }
118 return IRQ_HANDLED;
119 }
121 static int hdmi_init_regulator(void)
122 {
123 int r;
124 struct regulator *reg;
126 if (hdmi.vdda_reg != NULL)
127 return 0;
129 reg = devm_regulator_get(&hdmi.pdev->dev, "vdda");
130 if (IS_ERR(reg)) {
131 DSSERR("can't get VDDA regulator\n");
132 return PTR_ERR(reg);
133 }
135 if (regulator_can_change_voltage(reg)) {
136 r = regulator_set_voltage(reg, 1800000, 1800000);
137 if (r) {
138 devm_regulator_put(reg);
139 DSSWARN("can't set the regulator voltage\n");
140 return r;
141 }
142 }
144 hdmi.vdda_reg = reg;
146 return 0;
147 }
149 static int hdmi_pll_enable(struct pll_data *pll, struct hdmi_wp_data *wp,
150 struct pll_params *p)
151 {
152 u16 r = 0;
154 dss_ctrl_hdmi_pll_enable(true);
156 r = hdmi_wp_set_pll_pwr(wp, HDMI_PLLPWRCMD_ALLOFF);
157 if (r)
158 return r;
160 r = hdmi_wp_set_pll_pwr(wp, HDMI_PLLPWRCMD_BOTHON_ALLCLKS);
161 if (r)
162 return r;
164 pll_sysreset(pll);
166 r = pll_wait_reset(pll);
167 if (r)
168 return r;
170 r = pll_calc_and_check_clock_rates(pll, p);
171 if (r)
172 return r;
174 r = pll_set_clock_div(pll, p);
175 if (r)
176 return r;
178 return 0;
179 }
181 static void hdmi_pll_disable(struct hdmi_wp_data *wp)
182 {
183 hdmi_wp_set_pll_pwr(wp, HDMI_PLLPWRCMD_ALLOFF);
185 dss_ctrl_hdmi_pll_enable(false);
186 }
188 static int hdmi_power_on_core(struct omap_dss_device *dssdev)
189 {
190 int r;
192 r = regulator_enable(hdmi.vdda_reg);
193 if (r)
194 return r;
196 r = hdmi_runtime_get();
197 if (r)
198 goto err_runtime_get;
200 /* Make selection of HDMI in DSS */
201 dss_select_hdmi_venc_clk_source(DSS_HDMI_M_PCLK);
203 hdmi.core_enabled = true;
205 return 0;
207 err_runtime_get:
208 regulator_disable(hdmi.vdda_reg);
210 return r;
211 }
213 static void hdmi_power_off_core(struct omap_dss_device *dssdev)
214 {
215 hdmi.core_enabled = false;
217 hdmi_runtime_put();
218 regulator_disable(hdmi.vdda_reg);
219 }
221 static int hdmi_power_on_full(struct omap_dss_device *dssdev)
222 {
223 int r;
224 struct omap_video_timings *p;
225 struct omap_overlay_manager *mgr = hdmi.output.manager;
226 unsigned long phy;
227 struct pll_params param;
228 bool ok;
230 r = hdmi_power_on_core(dssdev);
231 if (r)
232 return r;
234 p = &hdmi.cfg.timings;
236 DSSDBG("hdmi_power_on x_res= %d y_res = %d\n", p->x_res, p->y_res);
238 phy = p->pixelclock * 10;
240 memset(¶m, 0, sizeof(param));
242 ok = pll_calc(hdmi.pll, phy, phy, NULL, ¶m);
243 if (!ok) {
244 DSSDBG("Failed to calculate PLL settings\n");
245 goto err_pll_enable;
246 }
248 /* disable and clear irqs */
249 hdmi_wp_clear_irqenable(&hdmi.wp, 0xffffffff);
250 hdmi_wp_set_irqstatus(&hdmi.wp,
251 hdmi_wp_get_irqstatus(&hdmi.wp));
253 /* config the PLL and PHY hdmi_set_pll_pwrfirst */
254 r = hdmi_pll_enable(hdmi.pll, &hdmi.wp, ¶m);
255 if (r) {
256 DSSDBG("Failed to lock PLL\n");
257 goto err_pll_enable;
258 }
260 r = hdmi_phy_configure(&hdmi.phy, &hdmi.cfg);
261 if (r) {
262 DSSDBG("Failed to start PHY\n");
263 goto err_phy_cfg;
264 }
266 r = hdmi_wp_set_phy_pwr(&hdmi.wp, HDMI_PHYPWRCMD_LDOON);
267 if (r)
268 goto err_phy_pwr;
270 hdmi5_configure(&hdmi.core, &hdmi.wp, &hdmi.cfg);
272 /* bypass TV gamma table */
273 dispc_enable_gamma_table(0);
275 /* tv size */
276 dss_mgr_set_timings(mgr, p);
278 r = dss_mgr_enable(mgr);
279 if (r)
280 goto err_mgr_enable;
282 r = hdmi_wp_video_start(&hdmi.wp);
283 if (r)
284 goto err_vid_enable;
286 hdmi_wp_set_irqenable(&hdmi.wp,
287 HDMI_IRQ_LINK_CONNECT | HDMI_IRQ_LINK_DISCONNECT);
289 return 0;
291 err_vid_enable:
292 dss_mgr_disable(mgr);
293 err_mgr_enable:
294 hdmi_wp_set_phy_pwr(&hdmi.wp, HDMI_PHYPWRCMD_OFF);
295 err_phy_pwr:
296 err_phy_cfg:
297 hdmi_pll_disable(&hdmi.wp);
298 err_pll_enable:
299 hdmi_power_off_core(dssdev);
300 return -EIO;
301 }
303 static void hdmi_power_off_full(struct omap_dss_device *dssdev)
304 {
305 struct omap_overlay_manager *mgr = hdmi.output.manager;
307 hdmi_wp_clear_irqenable(&hdmi.wp, 0xffffffff);
309 hdmi_wp_video_stop(&hdmi.wp);
311 dss_mgr_disable(mgr);
313 hdmi_wp_set_phy_pwr(&hdmi.wp, HDMI_PHYPWRCMD_OFF);
315 hdmi_pll_disable(&hdmi.wp);
317 hdmi_power_off_core(dssdev);
318 }
320 static int hdmi_display_check_timing(struct omap_dss_device *dssdev,
321 struct omap_video_timings *timings)
322 {
323 struct omap_dss_device *out = &hdmi.output;
325 if (!dispc_mgr_timings_ok(out->dispc_channel, timings))
326 return -EINVAL;
328 return 0;
329 }
331 static void hdmi_display_set_timing(struct omap_dss_device *dssdev,
332 struct omap_video_timings *timings)
333 {
334 mutex_lock(&hdmi.lock);
336 hdmi.cfg.timings = *timings;
338 dispc_set_tv_pclk(timings->pixelclock);
340 mutex_unlock(&hdmi.lock);
341 }
343 static void hdmi_display_get_timings(struct omap_dss_device *dssdev,
344 struct omap_video_timings *timings)
345 {
346 *timings = hdmi.cfg.timings;
347 }
349 static void hdmi_dump_regs(struct seq_file *s)
350 {
351 mutex_lock(&hdmi.lock);
353 if (hdmi_runtime_get()) {
354 mutex_unlock(&hdmi.lock);
355 return;
356 }
358 hdmi_wp_dump(&hdmi.wp, s);
359 pll_dump(hdmi.pll, s);
360 hdmi_phy_dump(&hdmi.phy, s);
361 hdmi5_core_dump(&hdmi.core, s);
363 hdmi_runtime_put();
364 mutex_unlock(&hdmi.lock);
365 }
367 static int read_edid(u8 *buf, int len)
368 {
369 int r;
370 int idlemode;
372 mutex_lock(&hdmi.lock);
374 r = hdmi_runtime_get();
375 BUG_ON(r);
377 idlemode = REG_GET(hdmi.wp.base, HDMI_WP_SYSCONFIG, 3, 2);
378 /* No-idle mode */
379 REG_FLD_MOD(hdmi.wp.base, HDMI_WP_SYSCONFIG, 1, 3, 2);
381 r = hdmi5_read_edid(&hdmi.core, buf, len);
383 REG_FLD_MOD(hdmi.wp.base, HDMI_WP_SYSCONFIG, idlemode, 3, 2);
385 hdmi_runtime_put();
386 mutex_unlock(&hdmi.lock);
388 return r;
389 }
391 static int hdmi_display_enable(struct omap_dss_device *dssdev)
392 {
393 struct omap_dss_device *out = &hdmi.output;
394 int r = 0;
396 DSSDBG("ENTER hdmi_display_enable\n");
398 mutex_lock(&hdmi.lock);
400 if (out == NULL || out->manager == NULL) {
401 DSSERR("failed to enable display: no output/manager\n");
402 r = -ENODEV;
403 goto err0;
404 }
406 r = hdmi_power_on_full(dssdev);
407 if (r) {
408 DSSERR("failed to power on device\n");
409 goto err0;
410 }
412 hdmi.display_enabled = true;
414 mutex_unlock(&hdmi.lock);
415 return 0;
417 err0:
418 mutex_unlock(&hdmi.lock);
419 return r;
420 }
422 static void hdmi_display_disable(struct omap_dss_device *dssdev)
423 {
424 DSSDBG("Enter hdmi_display_disable\n");
426 mutex_lock(&hdmi.lock);
428 /* If set hdmi.audio_abort_cb(&hdmi.pdev->dev) should be
429 * called here, if audio abort functionality is needed. */
431 hdmi_power_off_full(dssdev);
433 hdmi.display_enabled = false;
435 mutex_unlock(&hdmi.lock);
436 }
438 static int hdmi_core_enable(struct omap_dss_device *dssdev)
439 {
440 int r = 0;
442 DSSDBG("ENTER omapdss_hdmi_core_enable\n");
444 mutex_lock(&hdmi.lock);
446 r = hdmi_power_on_core(dssdev);
447 if (r) {
448 DSSERR("failed to power on device\n");
449 goto err0;
450 }
452 mutex_unlock(&hdmi.lock);
453 return 0;
455 err0:
456 mutex_unlock(&hdmi.lock);
457 return r;
458 }
460 static void hdmi_core_disable(struct omap_dss_device *dssdev)
461 {
462 DSSDBG("Enter omapdss_hdmi_core_disable\n");
464 mutex_lock(&hdmi.lock);
466 hdmi_power_off_core(dssdev);
468 mutex_unlock(&hdmi.lock);
469 }
471 static int hdmi_connect(struct omap_dss_device *dssdev,
472 struct omap_dss_device *dst)
473 {
474 struct omap_overlay_manager *mgr;
475 int r;
477 r = hdmi_init_regulator();
478 if (r)
479 return r;
481 mgr = omap_dss_get_overlay_manager(dssdev->dispc_channel);
482 if (!mgr)
483 return -ENODEV;
485 r = dss_mgr_connect(mgr, dssdev);
486 if (r)
487 return r;
489 r = omapdss_output_set_device(dssdev, dst);
490 if (r) {
491 DSSERR("failed to connect output to new device: %s\n",
492 dst->name);
493 dss_mgr_disconnect(mgr, dssdev);
494 return r;
495 }
497 return 0;
498 }
500 static void hdmi_disconnect(struct omap_dss_device *dssdev,
501 struct omap_dss_device *dst)
502 {
503 WARN_ON(dst != dssdev->dst);
505 if (dst != dssdev->dst)
506 return;
508 omapdss_output_unset_device(dssdev);
510 if (dssdev->manager)
511 dss_mgr_disconnect(dssdev->manager, dssdev);
512 }
514 static int hdmi_read_edid(struct omap_dss_device *dssdev,
515 u8 *edid, int len)
516 {
517 bool need_enable;
518 int r;
520 need_enable = hdmi.core_enabled == false;
522 if (need_enable) {
523 r = hdmi_core_enable(dssdev);
524 if (r)
525 return r;
526 }
528 r = read_edid(edid, len);
530 if (need_enable)
531 hdmi_core_disable(dssdev);
533 return r;
534 }
536 static int hdmi_set_infoframe(struct omap_dss_device *dssdev,
537 const struct hdmi_avi_infoframe *avi)
538 {
539 hdmi.cfg.infoframe = *avi;
540 return 0;
541 }
543 static int hdmi_set_hdmi_mode(struct omap_dss_device *dssdev,
544 bool hdmi_mode)
545 {
546 hdmi.cfg.hdmi_dvi_mode = hdmi_mode ? HDMI_HDMI : HDMI_DVI;
547 return 0;
548 }
550 static const struct omapdss_hdmi_ops hdmi_ops = {
551 .connect = hdmi_connect,
552 .disconnect = hdmi_disconnect,
554 .enable = hdmi_display_enable,
555 .disable = hdmi_display_disable,
557 .check_timings = hdmi_display_check_timing,
558 .set_timings = hdmi_display_set_timing,
559 .get_timings = hdmi_display_get_timings,
561 .read_edid = hdmi_read_edid,
562 .set_infoframe = hdmi_set_infoframe,
563 .set_hdmi_mode = hdmi_set_hdmi_mode,
564 };
566 static void hdmi_init_output(struct platform_device *pdev)
567 {
568 struct omap_dss_device *out = &hdmi.output;
570 out->dev = &pdev->dev;
571 out->id = OMAP_DSS_OUTPUT_HDMI;
572 out->output_type = OMAP_DISPLAY_TYPE_HDMI;
573 out->name = "hdmi.0";
574 out->dispc_channel = OMAP_DSS_CHANNEL_DIGIT;
575 out->ops.hdmi = &hdmi_ops;
576 out->owner = THIS_MODULE;
578 omapdss_register_output(out);
579 }
581 static void __exit hdmi_uninit_output(struct platform_device *pdev)
582 {
583 struct omap_dss_device *out = &hdmi.output;
585 omapdss_unregister_output(out);
586 }
588 static int hdmi_probe_of(struct platform_device *pdev)
589 {
590 struct device_node *node = pdev->dev.of_node;
591 struct device_node *ep;
592 int r;
594 ep = omapdss_of_get_first_endpoint(node);
595 if (!ep)
596 return 0;
598 r = hdmi_parse_lanes_of(pdev, ep, &hdmi.phy);
599 if (r)
600 goto err;
602 of_node_put(ep);
603 return 0;
605 err:
606 of_node_put(ep);
607 return r;
608 }
610 #if defined(CONFIG_OMAP5_DSS_HDMI_AUDIO)
611 static int audio_startup(struct device *dev,
612 void (*abort_cb)(struct device *dev))
613 {
614 struct omap_hdmi *hd = dev_get_drvdata(dev);
615 int ret = 0;
617 mutex_lock(&hd->lock);
619 if (!hdmi_mode_has_audio(&hd->cfg) || !hd->display_enabled) {
620 ret = -EPERM;
621 goto out;
622 }
624 hd->audio_abort_cb = abort_cb;
626 out:
627 mutex_unlock(&hd->lock);
629 return ret;
630 }
632 static int audio_enable(struct device *dev, bool enable)
633 {
634 struct omap_hdmi *hd = dev_get_drvdata(dev);
635 int ret;
637 mutex_lock(&hd->lock);
639 if (enable) {
640 /* No idle while playing audio */
641 hd->wp_idlemode =
642 REG_GET(hdmi.wp.base, HDMI_WP_SYSCONFIG, 3, 2);
643 REG_FLD_MOD(hdmi.wp.base, HDMI_WP_SYSCONFIG, 1, 3, 2);
644 }
646 ret = hdmi_wp_audio_enable(&hd->wp, enable);
648 if (!enable) {
649 /* Playback stopped, restore original idlemode */
650 REG_FLD_MOD(hdmi.wp.base, HDMI_WP_SYSCONFIG, hd->wp_idlemode,
651 3, 2);
653 hd->audio_abort_cb = NULL;
654 }
656 mutex_unlock(&hd->lock);
658 return ret;
659 }
661 static int audio_start(struct device *dev, bool enable)
662 {
663 struct omap_hdmi *hd = dev_get_drvdata(dev);
665 return hdmi_wp_audio_core_req_enable(&hd->wp, enable);
666 }
668 static int audio_config(struct device *dev, struct omap_dss_audio *dss_audio)
669 {
670 struct omap_hdmi *hd = dev_get_drvdata(dev);
671 int ret;
673 mutex_lock(&hd->lock);
674 if (!hdmi_mode_has_audio(&hd->cfg))
675 ret = -EPERM;
676 else
677 ret = hdmi5_audio_config(&hd->core, &hd->wp, dss_audio,
678 hd->cfg.timings.pixelclock);
679 mutex_unlock(&hd->lock);
681 return ret;
682 }
684 static int hdmi_audio_register(struct device *dev)
685 {
686 struct omap_hdmi_audio ha = {
687 .dev = dev,
688 .hw_version = OMAP5_HDMI,
689 .audio_dma_addr = hdmi_wp_get_audio_dma_addr(&hdmi.wp),
690 .audio_startup = audio_startup,
691 .audio_enable = audio_enable,
692 .audio_start = audio_start,
693 .audio_config = audio_config,
694 };
696 return omap_hdmi_audio_register(&ha);
697 }
698 #else /* CONFIG_OMAP5_DSS_HDMI_AUDIO */
699 static int hdmi_audio_register(struct device *dev)
700 {
701 return 0;
702 }
703 #endif
705 /* HDMI HW IP initialisation */
706 static int omapdss_hdmihw_probe(struct platform_device *pdev)
707 {
708 int r;
709 int irq;
711 hdmi.pdev = pdev;
712 dev_set_drvdata(&pdev->dev, &hdmi);
714 mutex_init(&hdmi.lock);
716 if (pdev->dev.of_node) {
717 r = hdmi_probe_of(pdev);
718 if (r)
719 return r;
720 }
722 r = hdmi_wp_init(pdev, &hdmi.wp);
723 if (r)
724 return r;
726 hdmi.pll = pll_create(pdev, "pll", "sys_clk", DSS_PLL_TYPE_HDMI,
727 NULL, 0);
728 if (!hdmi.pll)
729 return -ENODEV;
731 r = hdmi_phy_init(pdev, &hdmi.phy);
732 if (r)
733 return r;
735 r = hdmi5_core_init(pdev, &hdmi.core);
736 if (r)
737 return r;
739 irq = platform_get_irq(pdev, 0);
740 if (irq < 0) {
741 DSSERR("platform_get_irq failed\n");
742 return -ENODEV;
743 }
745 r = devm_request_threaded_irq(&pdev->dev, irq,
746 NULL, hdmi_irq_handler,
747 IRQF_ONESHOT, "OMAP HDMI", &hdmi.wp);
748 if (r) {
749 DSSERR("HDMI IRQ request failed\n");
750 return r;
751 }
753 hdmi.edev.name = "hdmi";
754 hdmi.edev.print_state = NULL;
756 r = extcon_dev_register(&hdmi.edev);
757 if (r)
758 return r;
760 /* Init extcon state to zero */
761 extcon_set_state(&hdmi.edev, 0);
763 pm_runtime_enable(&pdev->dev);
765 hdmi_init_output(pdev);
767 r = hdmi_audio_register(&pdev->dev);
768 if (r) {
769 DSSERR("Registering HDMI audio failed\n");
770 hdmi_uninit_output(pdev);
771 pm_runtime_disable(&pdev->dev);
772 extcon_dev_unregister(&hdmi.edev);
773 return r;
774 }
776 dss_debugfs_create_file("hdmi", hdmi_dump_regs);
778 return 0;
779 }
781 static int __exit omapdss_hdmihw_remove(struct platform_device *pdev)
782 {
783 omap_hdmi_audio_unregister(&pdev->dev);
785 hdmi_uninit_output(pdev);
787 pm_runtime_disable(&pdev->dev);
789 extcon_dev_unregister(&hdmi.edev);
791 return 0;
792 }
794 static int hdmi_runtime_suspend(struct device *dev)
795 {
796 pll_enable_clock(hdmi.pll, false);
798 dispc_runtime_put();
800 return 0;
801 }
803 static int hdmi_runtime_resume(struct device *dev)
804 {
805 int r;
807 r = dispc_runtime_get();
808 if (r < 0)
809 return r;
811 pll_enable_clock(hdmi.pll, true);
813 return 0;
814 }
816 static const struct dev_pm_ops hdmi_pm_ops = {
817 .runtime_suspend = hdmi_runtime_suspend,
818 .runtime_resume = hdmi_runtime_resume,
819 };
821 static const struct of_device_id hdmi_of_match[] = {
822 { .compatible = "ti,omap5-hdmi", },
823 { .compatible = "ti,dra7-hdmi", },
824 {},
825 };
827 static struct platform_driver omapdss_hdmihw_driver = {
828 .probe = omapdss_hdmihw_probe,
829 .remove = __exit_p(omapdss_hdmihw_remove),
830 .driver = {
831 .name = "omapdss_hdmi5",
832 .owner = THIS_MODULE,
833 .pm = &hdmi_pm_ops,
834 .of_match_table = hdmi_of_match,
835 },
836 };
838 int __init hdmi5_init_platform_driver(void)
839 {
840 return platform_driver_register(&omapdss_hdmihw_driver);
841 }
843 void __exit hdmi5_uninit_platform_driver(void)
844 {
845 platform_driver_unregister(&omapdss_hdmihw_driver);
846 }