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