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