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