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