]> Git Repo - J-linux.git/blob - drivers/video/fbdev/omap2/omapfb/dss/hdmi5.c
Merge tag 'amd-drm-next-6.5-2023-06-09' of https://gitlab.freedesktop.org/agd5f/linux...
[J-linux.git] / drivers / video / fbdev / omap2 / omapfb / dss / hdmi5.c
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 <[email protected]>
11  *      Tomi Valkeinen <[email protected]>
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
37 static struct omap_hdmi hdmi;
38
39 static 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
52 static 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
62 static 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
108 static 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
126 static 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
145 err_runtime_get:
146         regulator_disable(hdmi.vdda_reg);
147
148         return r;
149 }
150
151 static 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
159 static 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
225 err_mgr_enable:
226         hdmi_wp_video_stop(&hdmi.wp);
227 err_vid_enable:
228         hdmi_wp_set_phy_pwr(&hdmi.wp, HDMI_PHYPWRCMD_OFF);
229 err_phy_pwr:
230 err_phy_cfg:
231 err_pll_cfg:
232         dss_pll_disable(&hdmi.pll.pll);
233 err_pll_enable:
234         hdmi_power_off_core(dssdev);
235         return -EIO;
236 }
237
238 static 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
255 static 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
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
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
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         hdmi5_core_dump(&hdmi.core, s);
301
302         hdmi_runtime_put();
303         mutex_unlock(&hdmi.lock);
304 }
305
306 static 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
330 static 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
337 static 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
344 static 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
385 err0:
386         mutex_unlock(&hdmi.lock);
387         return r;
388 }
389
390 static 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
408 static 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
425 err0:
426         mutex_unlock(&hdmi.lock);
427         return r;
428 }
429
430 static 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
441 static 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
470 static 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
484 static 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
506 static 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
513 static 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
520 static 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
536 static 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
551 static 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
558 static 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
575 err:
576         of_node_put(ep);
577         return r;
578 }
579
580 /* Audio callbacks */
581 static 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
596 out:
597         mutex_unlock(&hd->lock);
598
599         return ret;
600 }
601
602 static 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
615 static 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
632 static 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
648 static 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         }
668 out:
669         mutex_unlock(&hd->lock);
670
671         return ret;
672 }
673
674 static 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
682 static 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 */
707 static 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;
771 err:
772         hdmi_pll_uninit(&hdmi.pll);
773         return r;
774 }
775
776 static 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
790 static const struct component_ops hdmi5_component_ops = {
791         .bind   = hdmi5_bind,
792         .unbind = hdmi5_unbind,
793 };
794
795 static int hdmi5_probe(struct platform_device *pdev)
796 {
797         return component_add(&pdev->dev, &hdmi5_component_ops);
798 }
799
800 static void hdmi5_remove(struct platform_device *pdev)
801 {
802         component_del(&pdev->dev, &hdmi5_component_ops);
803 }
804
805 static int hdmi_runtime_suspend(struct device *dev)
806 {
807         dispc_runtime_put();
808
809         return 0;
810 }
811
812 static 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
823 static const struct dev_pm_ops hdmi_pm_ops = {
824         .runtime_suspend = hdmi_runtime_suspend,
825         .runtime_resume = hdmi_runtime_resume,
826 };
827
828 static const struct of_device_id hdmi_of_match[] = {
829         { .compatible = "ti,omap5-hdmi", },
830         { .compatible = "ti,dra7-hdmi", },
831         {},
832 };
833
834 static 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
845 int __init hdmi5_init_platform_driver(void)
846 {
847         return platform_driver_register(&omapdss_hdmihw_driver);
848 }
849
850 void hdmi5_uninit_platform_driver(void)
851 {
852         platform_driver_unregister(&omapdss_hdmihw_driver);
853 }
This page took 0.078735 seconds and 4 git commands to generate.