xref: /openbmc/linux/drivers/gpu/drm/omapdrm/dss/hdmi4.c (revision 23c2b932)
1 /*
2  * HDMI interface DSS driver for TI's OMAP4 family of SoCs.
3  * Copyright (C) 2010-2011 Texas Instruments Incorporated - http://www.ti.com/
4  * Authors: Yong Zhi
5  *	Mythri pk <mythripk@ti.com>
6  *
7  * This program is free software; you can redistribute it and/or modify it
8  * under the terms of the GNU General Public License version 2 as published by
9  * the Free Software Foundation.
10  *
11  * This program is distributed in the hope that it will be useful, but WITHOUT
12  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
14  * more details.
15  *
16  * You should have received a copy of the GNU General Public License along with
17  * this program.  If not, see <http://www.gnu.org/licenses/>.
18  */
19 
20 #define DSS_SUBSYS_NAME "HDMI"
21 
22 #include <linux/kernel.h>
23 #include <linux/module.h>
24 #include <linux/err.h>
25 #include <linux/io.h>
26 #include <linux/interrupt.h>
27 #include <linux/mutex.h>
28 #include <linux/delay.h>
29 #include <linux/string.h>
30 #include <linux/platform_device.h>
31 #include <linux/pm_runtime.h>
32 #include <linux/clk.h>
33 #include <linux/gpio.h>
34 #include <linux/regulator/consumer.h>
35 #include <linux/component.h>
36 #include <linux/of.h>
37 #include <video/omapdss.h>
38 #include <sound/omap-hdmi-audio.h>
39 
40 #include "hdmi4_core.h"
41 #include "dss.h"
42 #include "dss_features.h"
43 #include "hdmi.h"
44 
45 static struct omap_hdmi hdmi;
46 
47 static int hdmi_runtime_get(void)
48 {
49 	int r;
50 
51 	DSSDBG("hdmi_runtime_get\n");
52 
53 	r = pm_runtime_get_sync(&hdmi.pdev->dev);
54 	WARN_ON(r < 0);
55 	if (r < 0)
56 		return r;
57 
58 	return 0;
59 }
60 
61 static void hdmi_runtime_put(void)
62 {
63 	int r;
64 
65 	DSSDBG("hdmi_runtime_put\n");
66 
67 	r = pm_runtime_put_sync(&hdmi.pdev->dev);
68 	WARN_ON(r < 0 && r != -ENOSYS);
69 }
70 
71 static irqreturn_t hdmi_irq_handler(int irq, void *data)
72 {
73 	struct hdmi_wp_data *wp = data;
74 	u32 irqstatus;
75 
76 	irqstatus = hdmi_wp_get_irqstatus(wp);
77 	hdmi_wp_set_irqstatus(wp, irqstatus);
78 
79 	if ((irqstatus & HDMI_IRQ_LINK_CONNECT) &&
80 			irqstatus & HDMI_IRQ_LINK_DISCONNECT) {
81 		/*
82 		 * If we get both connect and disconnect interrupts at the same
83 		 * time, turn off the PHY, clear interrupts, and restart, which
84 		 * raises connect interrupt if a cable is connected, or nothing
85 		 * if cable is not connected.
86 		 */
87 		hdmi_wp_set_phy_pwr(wp, HDMI_PHYPWRCMD_OFF);
88 
89 		hdmi_wp_set_irqstatus(wp, HDMI_IRQ_LINK_CONNECT |
90 				HDMI_IRQ_LINK_DISCONNECT);
91 
92 		hdmi_wp_set_phy_pwr(wp, HDMI_PHYPWRCMD_LDOON);
93 	} else if (irqstatus & HDMI_IRQ_LINK_CONNECT) {
94 		hdmi_wp_set_phy_pwr(wp, HDMI_PHYPWRCMD_TXON);
95 	} else if (irqstatus & HDMI_IRQ_LINK_DISCONNECT) {
96 		hdmi_wp_set_phy_pwr(wp, HDMI_PHYPWRCMD_LDOON);
97 	}
98 
99 	return IRQ_HANDLED;
100 }
101 
102 static int hdmi_init_regulator(void)
103 {
104 	struct regulator *reg;
105 
106 	if (hdmi.vdda_reg != NULL)
107 		return 0;
108 
109 	reg = devm_regulator_get(&hdmi.pdev->dev, "vdda");
110 
111 	if (IS_ERR(reg)) {
112 		if (PTR_ERR(reg) != -EPROBE_DEFER)
113 			DSSERR("can't get VDDA regulator\n");
114 		return PTR_ERR(reg);
115 	}
116 
117 	hdmi.vdda_reg = reg;
118 
119 	return 0;
120 }
121 
122 static int hdmi_power_on_core(struct omap_dss_device *dssdev)
123 {
124 	int r;
125 
126 	r = regulator_enable(hdmi.vdda_reg);
127 	if (r)
128 		return r;
129 
130 	r = hdmi_runtime_get();
131 	if (r)
132 		goto err_runtime_get;
133 
134 	/* Make selection of HDMI in DSS */
135 	dss_select_hdmi_venc_clk_source(DSS_HDMI_M_PCLK);
136 
137 	hdmi.core_enabled = true;
138 
139 	return 0;
140 
141 err_runtime_get:
142 	regulator_disable(hdmi.vdda_reg);
143 
144 	return r;
145 }
146 
147 static void hdmi_power_off_core(struct omap_dss_device *dssdev)
148 {
149 	hdmi.core_enabled = false;
150 
151 	hdmi_runtime_put();
152 	regulator_disable(hdmi.vdda_reg);
153 }
154 
155 static int hdmi_power_on_full(struct omap_dss_device *dssdev)
156 {
157 	int r;
158 	struct omap_video_timings *p;
159 	enum omap_channel channel = dssdev->dispc_channel;
160 	struct hdmi_wp_data *wp = &hdmi.wp;
161 	struct dss_pll_clock_info hdmi_cinfo = { 0 };
162 	unsigned pc;
163 
164 	r = hdmi_power_on_core(dssdev);
165 	if (r)
166 		return r;
167 
168 	/* disable and clear irqs */
169 	hdmi_wp_clear_irqenable(wp, 0xffffffff);
170 	hdmi_wp_set_irqstatus(wp, 0xffffffff);
171 
172 	p = &hdmi.cfg.timings;
173 
174 	DSSDBG("hdmi_power_on x_res= %d y_res = %d\n", p->x_res, p->y_res);
175 
176 	pc = p->pixelclock;
177 	if (p->double_pixel)
178 		pc *= 2;
179 
180 	hdmi_pll_compute(&hdmi.pll, pc, &hdmi_cinfo);
181 
182 	r = dss_pll_enable(&hdmi.pll.pll);
183 	if (r) {
184 		DSSERR("Failed to enable PLL\n");
185 		goto err_pll_enable;
186 	}
187 
188 	r = dss_pll_set_config(&hdmi.pll.pll, &hdmi_cinfo);
189 	if (r) {
190 		DSSERR("Failed to configure PLL\n");
191 		goto err_pll_cfg;
192 	}
193 
194 	r = hdmi_phy_configure(&hdmi.phy, hdmi_cinfo.clkdco,
195 		hdmi_cinfo.clkout[0]);
196 	if (r) {
197 		DSSDBG("Failed to configure PHY\n");
198 		goto err_phy_cfg;
199 	}
200 
201 	r = hdmi_wp_set_phy_pwr(wp, HDMI_PHYPWRCMD_LDOON);
202 	if (r)
203 		goto err_phy_pwr;
204 
205 	hdmi4_configure(&hdmi.core, &hdmi.wp, &hdmi.cfg);
206 
207 	/* bypass TV gamma table */
208 	dispc_enable_gamma_table(0);
209 
210 	/* tv size */
211 	dss_mgr_set_timings(channel, p);
212 
213 	r = dss_mgr_enable(channel);
214 	if (r)
215 		goto err_mgr_enable;
216 
217 	r = hdmi_wp_video_start(&hdmi.wp);
218 	if (r)
219 		goto err_vid_enable;
220 
221 	hdmi_wp_set_irqenable(wp,
222 		HDMI_IRQ_LINK_CONNECT | HDMI_IRQ_LINK_DISCONNECT);
223 
224 	return 0;
225 
226 err_vid_enable:
227 	dss_mgr_disable(channel);
228 err_mgr_enable:
229 	hdmi_wp_set_phy_pwr(&hdmi.wp, HDMI_PHYPWRCMD_OFF);
230 err_phy_pwr:
231 err_phy_cfg:
232 err_pll_cfg:
233 	dss_pll_disable(&hdmi.pll.pll);
234 err_pll_enable:
235 	hdmi_power_off_core(dssdev);
236 	return -EIO;
237 }
238 
239 static void hdmi_power_off_full(struct omap_dss_device *dssdev)
240 {
241 	enum omap_channel channel = dssdev->dispc_channel;
242 
243 	hdmi_wp_clear_irqenable(&hdmi.wp, 0xffffffff);
244 
245 	hdmi_wp_video_stop(&hdmi.wp);
246 
247 	dss_mgr_disable(channel);
248 
249 	hdmi_wp_set_phy_pwr(&hdmi.wp, HDMI_PHYPWRCMD_OFF);
250 
251 	dss_pll_disable(&hdmi.pll.pll);
252 
253 	hdmi_power_off_core(dssdev);
254 }
255 
256 static int hdmi_display_check_timing(struct omap_dss_device *dssdev,
257 					struct omap_video_timings *timings)
258 {
259 	if (!dispc_mgr_timings_ok(dssdev->dispc_channel, timings))
260 		return -EINVAL;
261 
262 	return 0;
263 }
264 
265 static void hdmi_display_set_timing(struct omap_dss_device *dssdev,
266 		struct omap_video_timings *timings)
267 {
268 	mutex_lock(&hdmi.lock);
269 
270 	hdmi.cfg.timings = *timings;
271 
272 	dispc_set_tv_pclk(timings->pixelclock);
273 
274 	mutex_unlock(&hdmi.lock);
275 }
276 
277 static void hdmi_display_get_timings(struct omap_dss_device *dssdev,
278 		struct omap_video_timings *timings)
279 {
280 	*timings = hdmi.cfg.timings;
281 }
282 
283 static void hdmi_dump_regs(struct seq_file *s)
284 {
285 	mutex_lock(&hdmi.lock);
286 
287 	if (hdmi_runtime_get()) {
288 		mutex_unlock(&hdmi.lock);
289 		return;
290 	}
291 
292 	hdmi_wp_dump(&hdmi.wp, s);
293 	hdmi_pll_dump(&hdmi.pll, s);
294 	hdmi_phy_dump(&hdmi.phy, s);
295 	hdmi4_core_dump(&hdmi.core, s);
296 
297 	hdmi_runtime_put();
298 	mutex_unlock(&hdmi.lock);
299 }
300 
301 static int read_edid(u8 *buf, int len)
302 {
303 	int r;
304 
305 	mutex_lock(&hdmi.lock);
306 
307 	r = hdmi_runtime_get();
308 	BUG_ON(r);
309 
310 	r = hdmi4_read_edid(&hdmi.core,  buf, len);
311 
312 	hdmi_runtime_put();
313 	mutex_unlock(&hdmi.lock);
314 
315 	return r;
316 }
317 
318 static void hdmi_start_audio_stream(struct omap_hdmi *hd)
319 {
320 	hdmi_wp_audio_enable(&hd->wp, true);
321 	hdmi4_audio_start(&hd->core, &hd->wp);
322 }
323 
324 static void hdmi_stop_audio_stream(struct omap_hdmi *hd)
325 {
326 	hdmi4_audio_stop(&hd->core, &hd->wp);
327 	hdmi_wp_audio_enable(&hd->wp, false);
328 }
329 
330 static int hdmi_display_enable(struct omap_dss_device *dssdev)
331 {
332 	struct omap_dss_device *out = &hdmi.output;
333 	unsigned long flags;
334 	int r = 0;
335 
336 	DSSDBG("ENTER hdmi_display_enable\n");
337 
338 	mutex_lock(&hdmi.lock);
339 
340 	if (!out->dispc_channel_connected) {
341 		DSSERR("failed to enable display: no output/manager\n");
342 		r = -ENODEV;
343 		goto err0;
344 	}
345 
346 	r = hdmi_power_on_full(dssdev);
347 	if (r) {
348 		DSSERR("failed to power on device\n");
349 		goto err0;
350 	}
351 
352 	if (hdmi.audio_configured) {
353 		r = hdmi4_audio_config(&hdmi.core, &hdmi.wp, &hdmi.audio_config,
354 				       hdmi.cfg.timings.pixelclock);
355 		if (r) {
356 			DSSERR("Error restoring audio configuration: %d", r);
357 			hdmi.audio_abort_cb(&hdmi.pdev->dev);
358 			hdmi.audio_configured = false;
359 		}
360 	}
361 
362 	spin_lock_irqsave(&hdmi.audio_playing_lock, flags);
363 	if (hdmi.audio_configured && hdmi.audio_playing)
364 		hdmi_start_audio_stream(&hdmi);
365 	hdmi.display_enabled = true;
366 	spin_unlock_irqrestore(&hdmi.audio_playing_lock, flags);
367 
368 	mutex_unlock(&hdmi.lock);
369 	return 0;
370 
371 err0:
372 	mutex_unlock(&hdmi.lock);
373 	return r;
374 }
375 
376 static void hdmi_display_disable(struct omap_dss_device *dssdev)
377 {
378 	unsigned long flags;
379 
380 	DSSDBG("Enter hdmi_display_disable\n");
381 
382 	mutex_lock(&hdmi.lock);
383 
384 	spin_lock_irqsave(&hdmi.audio_playing_lock, flags);
385 	hdmi_stop_audio_stream(&hdmi);
386 	hdmi.display_enabled = false;
387 	spin_unlock_irqrestore(&hdmi.audio_playing_lock, flags);
388 
389 	hdmi_power_off_full(dssdev);
390 
391 	mutex_unlock(&hdmi.lock);
392 }
393 
394 static int hdmi_core_enable(struct omap_dss_device *dssdev)
395 {
396 	int r = 0;
397 
398 	DSSDBG("ENTER omapdss_hdmi_core_enable\n");
399 
400 	mutex_lock(&hdmi.lock);
401 
402 	r = hdmi_power_on_core(dssdev);
403 	if (r) {
404 		DSSERR("failed to power on device\n");
405 		goto err0;
406 	}
407 
408 	mutex_unlock(&hdmi.lock);
409 	return 0;
410 
411 err0:
412 	mutex_unlock(&hdmi.lock);
413 	return r;
414 }
415 
416 static void hdmi_core_disable(struct omap_dss_device *dssdev)
417 {
418 	DSSDBG("Enter omapdss_hdmi_core_disable\n");
419 
420 	mutex_lock(&hdmi.lock);
421 
422 	hdmi_power_off_core(dssdev);
423 
424 	mutex_unlock(&hdmi.lock);
425 }
426 
427 static int hdmi_connect(struct omap_dss_device *dssdev,
428 		struct omap_dss_device *dst)
429 {
430 	enum omap_channel channel = dssdev->dispc_channel;
431 	int r;
432 
433 	r = hdmi_init_regulator();
434 	if (r)
435 		return r;
436 
437 	r = dss_mgr_connect(channel, dssdev);
438 	if (r)
439 		return r;
440 
441 	r = omapdss_output_set_device(dssdev, dst);
442 	if (r) {
443 		DSSERR("failed to connect output to new device: %s\n",
444 				dst->name);
445 		dss_mgr_disconnect(channel, dssdev);
446 		return r;
447 	}
448 
449 	return 0;
450 }
451 
452 static void hdmi_disconnect(struct omap_dss_device *dssdev,
453 		struct omap_dss_device *dst)
454 {
455 	enum omap_channel channel = dssdev->dispc_channel;
456 
457 	WARN_ON(dst != dssdev->dst);
458 
459 	if (dst != dssdev->dst)
460 		return;
461 
462 	omapdss_output_unset_device(dssdev);
463 
464 	dss_mgr_disconnect(channel, dssdev);
465 }
466 
467 static int hdmi_read_edid(struct omap_dss_device *dssdev,
468 		u8 *edid, int len)
469 {
470 	bool need_enable;
471 	int r;
472 
473 	need_enable = hdmi.core_enabled == false;
474 
475 	if (need_enable) {
476 		r = hdmi_core_enable(dssdev);
477 		if (r)
478 			return r;
479 	}
480 
481 	r = read_edid(edid, len);
482 
483 	if (need_enable)
484 		hdmi_core_disable(dssdev);
485 
486 	return r;
487 }
488 
489 static int hdmi_set_infoframe(struct omap_dss_device *dssdev,
490 		const struct hdmi_avi_infoframe *avi)
491 {
492 	hdmi.cfg.infoframe = *avi;
493 	return 0;
494 }
495 
496 static int hdmi_set_hdmi_mode(struct omap_dss_device *dssdev,
497 		bool hdmi_mode)
498 {
499 	hdmi.cfg.hdmi_dvi_mode = hdmi_mode ? HDMI_HDMI : HDMI_DVI;
500 	return 0;
501 }
502 
503 static const struct omapdss_hdmi_ops hdmi_ops = {
504 	.connect		= hdmi_connect,
505 	.disconnect		= hdmi_disconnect,
506 
507 	.enable			= hdmi_display_enable,
508 	.disable		= hdmi_display_disable,
509 
510 	.check_timings		= hdmi_display_check_timing,
511 	.set_timings		= hdmi_display_set_timing,
512 	.get_timings		= hdmi_display_get_timings,
513 
514 	.read_edid		= hdmi_read_edid,
515 	.set_infoframe		= hdmi_set_infoframe,
516 	.set_hdmi_mode		= hdmi_set_hdmi_mode,
517 };
518 
519 static void hdmi_init_output(struct platform_device *pdev)
520 {
521 	struct omap_dss_device *out = &hdmi.output;
522 
523 	out->dev = &pdev->dev;
524 	out->id = OMAP_DSS_OUTPUT_HDMI;
525 	out->output_type = OMAP_DISPLAY_TYPE_HDMI;
526 	out->name = "hdmi.0";
527 	out->dispc_channel = OMAP_DSS_CHANNEL_DIGIT;
528 	out->ops.hdmi = &hdmi_ops;
529 	out->owner = THIS_MODULE;
530 
531 	omapdss_register_output(out);
532 }
533 
534 static void hdmi_uninit_output(struct platform_device *pdev)
535 {
536 	struct omap_dss_device *out = &hdmi.output;
537 
538 	omapdss_unregister_output(out);
539 }
540 
541 static int hdmi_probe_of(struct platform_device *pdev)
542 {
543 	struct device_node *node = pdev->dev.of_node;
544 	struct device_node *ep;
545 	int r;
546 
547 	ep = omapdss_of_get_first_endpoint(node);
548 	if (!ep)
549 		return 0;
550 
551 	r = hdmi_parse_lanes_of(pdev, ep, &hdmi.phy);
552 	if (r)
553 		goto err;
554 
555 	of_node_put(ep);
556 	return 0;
557 
558 err:
559 	of_node_put(ep);
560 	return r;
561 }
562 
563 /* Audio callbacks */
564 static int hdmi_audio_startup(struct device *dev,
565 			      void (*abort_cb)(struct device *dev))
566 {
567 	struct omap_hdmi *hd = dev_get_drvdata(dev);
568 	int ret = 0;
569 
570 	mutex_lock(&hd->lock);
571 
572 	if (!hdmi_mode_has_audio(&hd->cfg) || !hd->display_enabled) {
573 		ret = -EPERM;
574 		goto out;
575 	}
576 
577 	hd->audio_abort_cb = abort_cb;
578 
579 out:
580 	mutex_unlock(&hd->lock);
581 
582 	return ret;
583 }
584 
585 static int hdmi_audio_shutdown(struct device *dev)
586 {
587 	struct omap_hdmi *hd = dev_get_drvdata(dev);
588 
589 	mutex_lock(&hd->lock);
590 	hd->audio_abort_cb = NULL;
591 	hd->audio_configured = false;
592 	hd->audio_playing = false;
593 	mutex_unlock(&hd->lock);
594 
595 	return 0;
596 }
597 
598 static int hdmi_audio_start(struct device *dev)
599 {
600 	struct omap_hdmi *hd = dev_get_drvdata(dev);
601 	unsigned long flags;
602 
603 	WARN_ON(!hdmi_mode_has_audio(&hd->cfg));
604 
605 	spin_lock_irqsave(&hd->audio_playing_lock, flags);
606 
607 	if (hd->display_enabled)
608 		hdmi_start_audio_stream(hd);
609 	hd->audio_playing = true;
610 
611 	spin_unlock_irqrestore(&hd->audio_playing_lock, flags);
612 	return 0;
613 }
614 
615 static void hdmi_audio_stop(struct device *dev)
616 {
617 	struct omap_hdmi *hd = dev_get_drvdata(dev);
618 	unsigned long flags;
619 
620 	WARN_ON(!hdmi_mode_has_audio(&hd->cfg));
621 
622 	spin_lock_irqsave(&hd->audio_playing_lock, flags);
623 
624 	if (hd->display_enabled)
625 		hdmi_stop_audio_stream(hd);
626 	hd->audio_playing = false;
627 
628 	spin_unlock_irqrestore(&hd->audio_playing_lock, flags);
629 }
630 
631 static int hdmi_audio_config(struct device *dev,
632 			     struct omap_dss_audio *dss_audio)
633 {
634 	struct omap_hdmi *hd = dev_get_drvdata(dev);
635 	int ret;
636 
637 	mutex_lock(&hd->lock);
638 
639 	if (!hdmi_mode_has_audio(&hd->cfg) || !hd->display_enabled) {
640 		ret = -EPERM;
641 		goto out;
642 	}
643 
644 	ret = hdmi4_audio_config(&hd->core, &hd->wp, dss_audio,
645 				 hd->cfg.timings.pixelclock);
646 	if (!ret) {
647 		hd->audio_configured = true;
648 		hd->audio_config = *dss_audio;
649 	}
650 out:
651 	mutex_unlock(&hd->lock);
652 
653 	return ret;
654 }
655 
656 static const struct omap_hdmi_audio_ops hdmi_audio_ops = {
657 	.audio_startup = hdmi_audio_startup,
658 	.audio_shutdown = hdmi_audio_shutdown,
659 	.audio_start = hdmi_audio_start,
660 	.audio_stop = hdmi_audio_stop,
661 	.audio_config = hdmi_audio_config,
662 };
663 
664 static int hdmi_audio_register(struct device *dev)
665 {
666 	struct omap_hdmi_audio_pdata pdata = {
667 		.dev = dev,
668 		.dss_version = omapdss_get_version(),
669 		.audio_dma_addr = hdmi_wp_get_audio_dma_addr(&hdmi.wp),
670 		.ops = &hdmi_audio_ops,
671 	};
672 
673 	hdmi.audio_pdev = platform_device_register_data(
674 		dev, "omap-hdmi-audio", PLATFORM_DEVID_AUTO,
675 		&pdata, sizeof(pdata));
676 
677 	if (IS_ERR(hdmi.audio_pdev))
678 		return PTR_ERR(hdmi.audio_pdev);
679 
680 	return 0;
681 }
682 
683 /* HDMI HW IP initialisation */
684 static int hdmi4_bind(struct device *dev, struct device *master, void *data)
685 {
686 	struct platform_device *pdev = to_platform_device(dev);
687 	int r;
688 	int irq;
689 
690 	hdmi.pdev = pdev;
691 	dev_set_drvdata(&pdev->dev, &hdmi);
692 
693 	mutex_init(&hdmi.lock);
694 	spin_lock_init(&hdmi.audio_playing_lock);
695 
696 	if (pdev->dev.of_node) {
697 		r = hdmi_probe_of(pdev);
698 		if (r)
699 			return r;
700 	}
701 
702 	r = hdmi_wp_init(pdev, &hdmi.wp);
703 	if (r)
704 		return r;
705 
706 	r = hdmi_pll_init(pdev, &hdmi.pll, &hdmi.wp);
707 	if (r)
708 		return r;
709 
710 	r = hdmi_phy_init(pdev, &hdmi.phy);
711 	if (r)
712 		goto err;
713 
714 	r = hdmi4_core_init(pdev, &hdmi.core);
715 	if (r)
716 		goto err;
717 
718 	irq = platform_get_irq(pdev, 0);
719 	if (irq < 0) {
720 		DSSERR("platform_get_irq failed\n");
721 		r = -ENODEV;
722 		goto err;
723 	}
724 
725 	r = devm_request_threaded_irq(&pdev->dev, irq,
726 			NULL, hdmi_irq_handler,
727 			IRQF_ONESHOT, "OMAP HDMI", &hdmi.wp);
728 	if (r) {
729 		DSSERR("HDMI IRQ request failed\n");
730 		goto err;
731 	}
732 
733 	pm_runtime_enable(&pdev->dev);
734 
735 	hdmi_init_output(pdev);
736 
737 	r = hdmi_audio_register(&pdev->dev);
738 	if (r) {
739 		DSSERR("Registering HDMI audio failed\n");
740 		hdmi_uninit_output(pdev);
741 		pm_runtime_disable(&pdev->dev);
742 		return r;
743 	}
744 
745 	dss_debugfs_create_file("hdmi", hdmi_dump_regs);
746 
747 	return 0;
748 err:
749 	hdmi_pll_uninit(&hdmi.pll);
750 	return r;
751 }
752 
753 static void hdmi4_unbind(struct device *dev, struct device *master, void *data)
754 {
755 	struct platform_device *pdev = to_platform_device(dev);
756 
757 	if (hdmi.audio_pdev)
758 		platform_device_unregister(hdmi.audio_pdev);
759 
760 	hdmi_uninit_output(pdev);
761 
762 	hdmi_pll_uninit(&hdmi.pll);
763 
764 	pm_runtime_disable(&pdev->dev);
765 }
766 
767 static const struct component_ops hdmi4_component_ops = {
768 	.bind	= hdmi4_bind,
769 	.unbind	= hdmi4_unbind,
770 };
771 
772 static int hdmi4_probe(struct platform_device *pdev)
773 {
774 	return component_add(&pdev->dev, &hdmi4_component_ops);
775 }
776 
777 static int hdmi4_remove(struct platform_device *pdev)
778 {
779 	component_del(&pdev->dev, &hdmi4_component_ops);
780 	return 0;
781 }
782 
783 static int hdmi_runtime_suspend(struct device *dev)
784 {
785 	dispc_runtime_put();
786 
787 	return 0;
788 }
789 
790 static int hdmi_runtime_resume(struct device *dev)
791 {
792 	int r;
793 
794 	r = dispc_runtime_get();
795 	if (r < 0)
796 		return r;
797 
798 	return 0;
799 }
800 
801 static const struct dev_pm_ops hdmi_pm_ops = {
802 	.runtime_suspend = hdmi_runtime_suspend,
803 	.runtime_resume = hdmi_runtime_resume,
804 };
805 
806 static const struct of_device_id hdmi_of_match[] = {
807 	{ .compatible = "ti,omap4-hdmi", },
808 	{},
809 };
810 
811 static struct platform_driver omapdss_hdmihw_driver = {
812 	.probe		= hdmi4_probe,
813 	.remove		= hdmi4_remove,
814 	.driver         = {
815 		.name   = "omapdss_hdmi",
816 		.pm	= &hdmi_pm_ops,
817 		.of_match_table = hdmi_of_match,
818 		.suppress_bind_attrs = true,
819 	},
820 };
821 
822 int __init hdmi4_init_platform_driver(void)
823 {
824 	return platform_driver_register(&omapdss_hdmihw_driver);
825 }
826 
827 void hdmi4_uninit_platform_driver(void)
828 {
829 	platform_driver_unregister(&omapdss_hdmihw_driver);
830 }
831