4 * HDMI interface DSS driver setting for TI's OMAP4 family of processor.
5 * Copyright (C) 2010-2011 Texas Instruments Incorporated - http://www.ti.com/
7 * Mythri pk <mythripk@ti.com>
9 * This program is free software; you can redistribute it and/or modify it
10 * under the terms of the GNU General Public License version 2 as published by
11 * the Free Software Foundation.
13 * This program is distributed in the hope that it will be useful, but WITHOUT
14 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
15 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
18 * You should have received a copy of the GNU General Public License along with
19 * this program. If not, see <http://www.gnu.org/licenses/>.
22 #define DSS_SUBSYS_NAME "HDMI"
24 #include <linux/kernel.h>
25 #include <linux/module.h>
26 #include <linux/err.h>
28 #include <linux/interrupt.h>
29 #include <linux/mutex.h>
30 #include <linux/delay.h>
31 #include <linux/string.h>
32 #include <linux/platform_device.h>
33 #include <linux/pm_runtime.h>
34 #include <linux/clk.h>
35 #include <video/omapdss.h>
39 #include "dss_features.h"
42 #define HDMI_CORE_SYS 0x400
43 #define HDMI_CORE_AV 0x900
44 #define HDMI_PLLCTRL 0x200
45 #define HDMI_PHY 0x300
47 /* HDMI EDID Length move this */
48 #define HDMI_EDID_MAX_LENGTH 256
49 #define EDID_TIMING_DESCRIPTOR_SIZE 0x12
50 #define EDID_DESCRIPTOR_BLOCK0_ADDRESS 0x36
51 #define EDID_DESCRIPTOR_BLOCK1_ADDRESS 0x80
52 #define EDID_SIZE_BLOCK0_TIMING_DESCRIPTOR 4
53 #define EDID_SIZE_BLOCK1_TIMING_DESCRIPTOR 4
55 #define HDMI_DEFAULT_REGN 16
56 #define HDMI_DEFAULT_REGM2 1
60 struct platform_device
*pdev
;
61 struct hdmi_ip_data ip_data
;
67 * Logic for the below structure :
68 * user enters the CEA or VESA timings by specifying the HDMI/DVI code.
69 * There is a correspondence between CEA/VESA timing and code, please
70 * refer to section 6.3 in HDMI 1.3 specification for timing code.
72 * In the below structure, cea_vesa_timings corresponds to all OMAP4
73 * supported CEA and VESA timing values.code_cea corresponds to the CEA
74 * code, It is used to get the timing from cea_vesa_timing array.Similarly
75 * with code_vesa. Code_index is used for back mapping, that is once EDID
76 * is read from the TV, EDID is parsed to find the timing values and then
77 * map it to corresponding CEA or VESA index.
80 static const struct hdmi_config cea_timings
[] = {
82 { 640, 480, 25200, 96, 16, 48, 2, 10, 33,
83 OMAPDSS_SIG_ACTIVE_LOW
, OMAPDSS_SIG_ACTIVE_LOW
,
88 { 720, 480, 27027, 62, 16, 60, 6, 9, 30,
89 OMAPDSS_SIG_ACTIVE_LOW
, OMAPDSS_SIG_ACTIVE_LOW
,
94 { 1280, 720, 74250, 40, 110, 220, 5, 5, 20,
95 OMAPDSS_SIG_ACTIVE_HIGH
, OMAPDSS_SIG_ACTIVE_HIGH
,
100 { 1920, 540, 74250, 44, 88, 148, 5, 2, 15,
101 OMAPDSS_SIG_ACTIVE_HIGH
, OMAPDSS_SIG_ACTIVE_HIGH
,
106 { 1440, 240, 27027, 124, 38, 114, 3, 4, 15,
107 OMAPDSS_SIG_ACTIVE_LOW
, OMAPDSS_SIG_ACTIVE_LOW
,
112 { 1920, 1080, 148500, 44, 88, 148, 5, 4, 36,
113 OMAPDSS_SIG_ACTIVE_HIGH
, OMAPDSS_SIG_ACTIVE_HIGH
,
118 { 720, 576, 27000, 64, 12, 68, 5, 5, 39,
119 OMAPDSS_SIG_ACTIVE_LOW
, OMAPDSS_SIG_ACTIVE_LOW
,
124 { 1280, 720, 74250, 40, 440, 220, 5, 5, 20,
125 OMAPDSS_SIG_ACTIVE_HIGH
, OMAPDSS_SIG_ACTIVE_HIGH
,
130 { 1920, 540, 74250, 44, 528, 148, 5, 2, 15,
131 OMAPDSS_SIG_ACTIVE_HIGH
, OMAPDSS_SIG_ACTIVE_HIGH
,
136 { 1440, 288, 27000, 126, 24, 138, 3, 2, 19,
137 OMAPDSS_SIG_ACTIVE_LOW
, OMAPDSS_SIG_ACTIVE_LOW
,
142 { 1440, 576, 54000, 128, 24, 136, 5, 5, 39,
143 OMAPDSS_SIG_ACTIVE_LOW
, OMAPDSS_SIG_ACTIVE_LOW
,
148 { 1920, 1080, 148500, 44, 528, 148, 5, 4, 36,
149 OMAPDSS_SIG_ACTIVE_HIGH
, OMAPDSS_SIG_ACTIVE_HIGH
,
154 { 1920, 1080, 74250, 44, 638, 148, 5, 4, 36,
155 OMAPDSS_SIG_ACTIVE_HIGH
, OMAPDSS_SIG_ACTIVE_HIGH
,
160 { 2880, 480, 108108, 248, 64, 240, 6, 9, 30,
161 OMAPDSS_SIG_ACTIVE_LOW
, OMAPDSS_SIG_ACTIVE_LOW
,
166 { 2880, 576, 108000, 256, 48, 272, 5, 5, 39,
167 OMAPDSS_SIG_ACTIVE_LOW
, OMAPDSS_SIG_ACTIVE_LOW
,
173 static const struct hdmi_config vesa_timings
[] = {
176 { 640, 480, 25175, 96, 16, 48, 2, 11, 31,
177 OMAPDSS_SIG_ACTIVE_LOW
, OMAPDSS_SIG_ACTIVE_LOW
,
182 { 800, 600, 40000, 128, 40, 88, 4, 1, 23,
183 OMAPDSS_SIG_ACTIVE_HIGH
, OMAPDSS_SIG_ACTIVE_HIGH
,
188 { 848, 480, 33750, 112, 16, 112, 8, 6, 23,
189 OMAPDSS_SIG_ACTIVE_HIGH
, OMAPDSS_SIG_ACTIVE_HIGH
,
194 { 1280, 768, 79500, 128, 64, 192, 7, 3, 20,
195 OMAPDSS_SIG_ACTIVE_HIGH
, OMAPDSS_SIG_ACTIVE_LOW
,
200 { 1280, 800, 83500, 128, 72, 200, 6, 3, 22,
201 OMAPDSS_SIG_ACTIVE_HIGH
, OMAPDSS_SIG_ACTIVE_LOW
,
206 { 1360, 768, 85500, 112, 64, 256, 6, 3, 18,
207 OMAPDSS_SIG_ACTIVE_HIGH
, OMAPDSS_SIG_ACTIVE_HIGH
,
212 { 1280, 960, 108000, 112, 96, 312, 3, 1, 36,
213 OMAPDSS_SIG_ACTIVE_HIGH
, OMAPDSS_SIG_ACTIVE_HIGH
,
218 { 1280, 1024, 108000, 112, 48, 248, 3, 1, 38,
219 OMAPDSS_SIG_ACTIVE_HIGH
, OMAPDSS_SIG_ACTIVE_HIGH
,
224 { 1024, 768, 65000, 136, 24, 160, 6, 3, 29,
225 OMAPDSS_SIG_ACTIVE_LOW
, OMAPDSS_SIG_ACTIVE_LOW
,
230 { 1400, 1050, 121750, 144, 88, 232, 4, 3, 32,
231 OMAPDSS_SIG_ACTIVE_HIGH
, OMAPDSS_SIG_ACTIVE_LOW
,
236 { 1440, 900, 106500, 152, 80, 232, 6, 3, 25,
237 OMAPDSS_SIG_ACTIVE_HIGH
, OMAPDSS_SIG_ACTIVE_LOW
,
242 { 1680, 1050, 146250, 176 , 104, 280, 6, 3, 30,
243 OMAPDSS_SIG_ACTIVE_HIGH
, OMAPDSS_SIG_ACTIVE_LOW
,
248 { 1366, 768, 85500, 143, 70, 213, 3, 3, 24,
249 OMAPDSS_SIG_ACTIVE_HIGH
, OMAPDSS_SIG_ACTIVE_HIGH
,
254 { 1920, 1080, 148500, 44, 148, 80, 5, 4, 36,
255 OMAPDSS_SIG_ACTIVE_HIGH
, OMAPDSS_SIG_ACTIVE_HIGH
,
260 { 1280, 768, 68250, 32, 48, 80, 7, 3, 12,
261 OMAPDSS_SIG_ACTIVE_LOW
, OMAPDSS_SIG_ACTIVE_HIGH
,
266 { 1400, 1050, 101000, 32, 48, 80, 4, 3, 23,
267 OMAPDSS_SIG_ACTIVE_LOW
, OMAPDSS_SIG_ACTIVE_HIGH
,
272 { 1680, 1050, 119000, 32, 48, 80, 6, 3, 21,
273 OMAPDSS_SIG_ACTIVE_LOW
, OMAPDSS_SIG_ACTIVE_HIGH
,
278 { 1280, 800, 79500, 32, 48, 80, 6, 3, 14,
279 OMAPDSS_SIG_ACTIVE_LOW
, OMAPDSS_SIG_ACTIVE_HIGH
,
284 { 1280, 720, 74250, 40, 110, 220, 5, 5, 20,
285 OMAPDSS_SIG_ACTIVE_HIGH
, OMAPDSS_SIG_ACTIVE_HIGH
,
291 static int hdmi_runtime_get(void)
295 DSSDBG("hdmi_runtime_get\n");
297 r
= pm_runtime_get_sync(&hdmi
.pdev
->dev
);
305 static void hdmi_runtime_put(void)
309 DSSDBG("hdmi_runtime_put\n");
311 r
= pm_runtime_put_sync(&hdmi
.pdev
->dev
);
312 WARN_ON(r
< 0 && r
!= -ENOSYS
);
315 static int __init
hdmi_init_display(struct omap_dss_device
*dssdev
)
317 DSSDBG("init_display\n");
319 dss_init_hdmi_ip_ops(&hdmi
.ip_data
);
323 static const struct hdmi_config
*hdmi_find_timing(
324 const struct hdmi_config
*timings_arr
,
329 for (i
= 0; i
< len
; i
++) {
330 if (timings_arr
[i
].cm
.code
== hdmi
.ip_data
.cfg
.cm
.code
)
331 return &timings_arr
[i
];
336 static const struct hdmi_config
*hdmi_get_timings(void)
338 const struct hdmi_config
*arr
;
341 if (hdmi
.ip_data
.cfg
.cm
.mode
== HDMI_DVI
) {
343 len
= ARRAY_SIZE(vesa_timings
);
346 len
= ARRAY_SIZE(cea_timings
);
349 return hdmi_find_timing(arr
, len
);
352 static bool hdmi_timings_compare(struct omap_video_timings
*timing1
,
353 const struct omap_video_timings
*timing2
)
355 int timing1_vsync
, timing1_hsync
, timing2_vsync
, timing2_hsync
;
357 if ((timing2
->pixel_clock
== timing1
->pixel_clock
) &&
358 (timing2
->x_res
== timing1
->x_res
) &&
359 (timing2
->y_res
== timing1
->y_res
)) {
361 timing2_hsync
= timing2
->hfp
+ timing2
->hsw
+ timing2
->hbp
;
362 timing1_hsync
= timing1
->hfp
+ timing1
->hsw
+ timing1
->hbp
;
363 timing2_vsync
= timing2
->vfp
+ timing2
->vsw
+ timing2
->vbp
;
364 timing1_vsync
= timing2
->vfp
+ timing2
->vsw
+ timing2
->vbp
;
366 DSSDBG("timing1_hsync = %d timing1_vsync = %d"\
367 "timing2_hsync = %d timing2_vsync = %d\n",
368 timing1_hsync
, timing1_vsync
,
369 timing2_hsync
, timing2_vsync
);
371 if ((timing1_hsync
== timing2_hsync
) &&
372 (timing1_vsync
== timing2_vsync
)) {
379 static struct hdmi_cm
hdmi_get_code(struct omap_video_timings
*timing
)
382 struct hdmi_cm cm
= {-1};
383 DSSDBG("hdmi_get_code\n");
385 for (i
= 0; i
< ARRAY_SIZE(cea_timings
); i
++) {
386 if (hdmi_timings_compare(timing
, &cea_timings
[i
].timings
)) {
387 cm
= cea_timings
[i
].cm
;
391 for (i
= 0; i
< ARRAY_SIZE(vesa_timings
); i
++) {
392 if (hdmi_timings_compare(timing
, &vesa_timings
[i
].timings
)) {
393 cm
= vesa_timings
[i
].cm
;
402 unsigned long hdmi_get_pixel_clock(void)
404 /* HDMI Pixel Clock in Mhz */
405 return hdmi
.ip_data
.cfg
.timings
.pixel_clock
* 1000;
408 static void hdmi_compute_pll(struct omap_dss_device
*dssdev
, int phy
,
409 struct hdmi_pll_info
*pi
)
411 unsigned long clkin
, refclk
;
414 clkin
= clk_get_rate(hdmi
.sys_clk
) / 10000;
416 * Input clock is predivided by N + 1
417 * out put of which is reference clk
419 if (dssdev
->clocks
.hdmi
.regn
== 0)
420 pi
->regn
= HDMI_DEFAULT_REGN
;
422 pi
->regn
= dssdev
->clocks
.hdmi
.regn
;
424 refclk
= clkin
/ pi
->regn
;
426 if (dssdev
->clocks
.hdmi
.regm2
== 0)
427 pi
->regm2
= HDMI_DEFAULT_REGM2
;
429 pi
->regm2
= dssdev
->clocks
.hdmi
.regm2
;
432 * multiplier is pixel_clk/ref_clk
433 * Multiplying by 100 to avoid fractional part removal
435 pi
->regm
= phy
* pi
->regm2
/ refclk
;
438 * fractional multiplier is remainder of the difference between
439 * multiplier and actual phy(required pixel clock thus should be
440 * multiplied by 2^18(262144) divided by the reference clock
442 mf
= (phy
- pi
->regm
/ pi
->regm2
* refclk
) * 262144;
443 pi
->regmf
= pi
->regm2
* mf
/ refclk
;
446 * Dcofreq should be set to 1 if required pixel clock
447 * is greater than 1000MHz
449 pi
->dcofreq
= phy
> 1000 * 100;
450 pi
->regsd
= ((pi
->regm
* clkin
/ 10) / (pi
->regn
* 250) + 5) / 10;
452 /* Set the reference clock to sysclk reference */
453 pi
->refsel
= HDMI_REFSEL_SYSCLK
;
455 DSSDBG("M = %d Mf = %d\n", pi
->regm
, pi
->regmf
);
456 DSSDBG("range = %d sd = %d\n", pi
->dcofreq
, pi
->regsd
);
459 static int hdmi_power_on(struct omap_dss_device
*dssdev
)
462 struct omap_video_timings
*p
;
465 r
= hdmi_runtime_get();
469 dss_mgr_disable(dssdev
->manager
);
471 p
= &hdmi
.ip_data
.cfg
.timings
;
473 DSSDBG("hdmi_power_on x_res= %d y_res = %d\n", p
->x_res
, p
->y_res
);
475 phy
= p
->pixel_clock
;
477 hdmi_compute_pll(dssdev
, phy
, &hdmi
.ip_data
.pll_data
);
479 hdmi
.ip_data
.ops
->video_disable(&hdmi
.ip_data
);
481 /* config the PLL and PHY hdmi_set_pll_pwrfirst */
482 r
= hdmi
.ip_data
.ops
->pll_enable(&hdmi
.ip_data
);
484 DSSDBG("Failed to lock PLL\n");
488 r
= hdmi
.ip_data
.ops
->phy_enable(&hdmi
.ip_data
);
490 DSSDBG("Failed to start PHY\n");
494 hdmi
.ip_data
.ops
->video_configure(&hdmi
.ip_data
);
496 /* Make selection of HDMI in DSS */
497 dss_select_hdmi_venc_clk_source(DSS_HDMI_M_PCLK
);
499 /* Select the dispc clock source as PRCM clock, to ensure that it is not
500 * DSI PLL source as the clock selected by DSI PLL might not be
501 * sufficient for the resolution selected / that can be changed
502 * dynamically by user. This can be moved to single location , say
505 dss_select_dispc_clk_source(dssdev
->clocks
.dispc
.dispc_fclk_src
);
507 /* bypass TV gamma table */
508 dispc_enable_gamma_table(0);
511 dss_mgr_set_timings(dssdev
->manager
, p
);
513 r
= hdmi
.ip_data
.ops
->video_enable(&hdmi
.ip_data
);
517 r
= dss_mgr_enable(dssdev
->manager
);
524 hdmi
.ip_data
.ops
->video_disable(&hdmi
.ip_data
);
526 hdmi
.ip_data
.ops
->phy_disable(&hdmi
.ip_data
);
528 hdmi
.ip_data
.ops
->pll_disable(&hdmi
.ip_data
);
534 static void hdmi_power_off(struct omap_dss_device
*dssdev
)
536 dss_mgr_disable(dssdev
->manager
);
538 hdmi
.ip_data
.ops
->video_disable(&hdmi
.ip_data
);
539 hdmi
.ip_data
.ops
->phy_disable(&hdmi
.ip_data
);
540 hdmi
.ip_data
.ops
->pll_disable(&hdmi
.ip_data
);
544 int omapdss_hdmi_display_check_timing(struct omap_dss_device
*dssdev
,
545 struct omap_video_timings
*timings
)
549 cm
= hdmi_get_code(timings
);
558 void omapdss_hdmi_display_set_timing(struct omap_dss_device
*dssdev
,
559 struct omap_video_timings
*timings
)
562 const struct hdmi_config
*t
;
564 mutex_lock(&hdmi
.lock
);
566 cm
= hdmi_get_code(timings
);
567 hdmi
.ip_data
.cfg
.cm
= cm
;
569 t
= hdmi_get_timings();
571 hdmi
.ip_data
.cfg
= *t
;
573 if (dssdev
->state
== OMAP_DSS_DISPLAY_ACTIVE
) {
576 hdmi_power_off(dssdev
);
578 r
= hdmi_power_on(dssdev
);
580 DSSERR("failed to power on device\n");
582 dss_mgr_set_timings(dssdev
->manager
, &t
->timings
);
585 mutex_unlock(&hdmi
.lock
);
588 static void hdmi_dump_regs(struct seq_file
*s
)
590 mutex_lock(&hdmi
.lock
);
592 if (hdmi_runtime_get())
595 hdmi
.ip_data
.ops
->dump_wrapper(&hdmi
.ip_data
, s
);
596 hdmi
.ip_data
.ops
->dump_pll(&hdmi
.ip_data
, s
);
597 hdmi
.ip_data
.ops
->dump_phy(&hdmi
.ip_data
, s
);
598 hdmi
.ip_data
.ops
->dump_core(&hdmi
.ip_data
, s
);
601 mutex_unlock(&hdmi
.lock
);
604 int omapdss_hdmi_read_edid(u8
*buf
, int len
)
608 mutex_lock(&hdmi
.lock
);
610 r
= hdmi_runtime_get();
613 r
= hdmi
.ip_data
.ops
->read_edid(&hdmi
.ip_data
, buf
, len
);
616 mutex_unlock(&hdmi
.lock
);
621 bool omapdss_hdmi_detect(void)
625 mutex_lock(&hdmi
.lock
);
627 r
= hdmi_runtime_get();
630 r
= hdmi
.ip_data
.ops
->detect(&hdmi
.ip_data
);
633 mutex_unlock(&hdmi
.lock
);
638 int omapdss_hdmi_display_enable(struct omap_dss_device
*dssdev
)
640 struct omap_dss_hdmi_data
*priv
= dssdev
->data
;
643 DSSDBG("ENTER hdmi_display_enable\n");
645 mutex_lock(&hdmi
.lock
);
647 if (dssdev
->manager
== NULL
) {
648 DSSERR("failed to enable display: no manager\n");
653 hdmi
.ip_data
.hpd_gpio
= priv
->hpd_gpio
;
655 r
= omap_dss_start_device(dssdev
);
657 DSSERR("failed to start device\n");
661 if (dssdev
->platform_enable
) {
662 r
= dssdev
->platform_enable(dssdev
);
664 DSSERR("failed to enable GPIO's\n");
669 r
= hdmi_power_on(dssdev
);
671 DSSERR("failed to power on device\n");
675 mutex_unlock(&hdmi
.lock
);
679 if (dssdev
->platform_disable
)
680 dssdev
->platform_disable(dssdev
);
682 omap_dss_stop_device(dssdev
);
684 mutex_unlock(&hdmi
.lock
);
688 void omapdss_hdmi_display_disable(struct omap_dss_device
*dssdev
)
690 DSSDBG("Enter hdmi_display_disable\n");
692 mutex_lock(&hdmi
.lock
);
694 hdmi_power_off(dssdev
);
696 if (dssdev
->platform_disable
)
697 dssdev
->platform_disable(dssdev
);
699 omap_dss_stop_device(dssdev
);
701 mutex_unlock(&hdmi
.lock
);
704 static int hdmi_get_clocks(struct platform_device
*pdev
)
708 clk
= clk_get(&pdev
->dev
, "sys_clk");
710 DSSERR("can't get sys_clk\n");
719 static void hdmi_put_clocks(void)
722 clk_put(hdmi
.sys_clk
);
725 #if defined(CONFIG_OMAP4_DSS_HDMI_AUDIO)
726 int hdmi_compute_acr(u32 sample_freq
, u32
*n
, u32
*cts
)
729 bool deep_color_correct
= false;
730 u32 pclk
= hdmi
.ip_data
.cfg
.timings
.pixel_clock
;
732 if (n
== NULL
|| cts
== NULL
)
735 /* TODO: When implemented, query deep color mode here. */
739 * When using deep color, the default N value (as in the HDMI
740 * specification) yields to an non-integer CTS. Hence, we
741 * modify it while keeping the restrictions described in
742 * section 7.2.1 of the HDMI 1.4a specification.
744 switch (sample_freq
) {
749 if (deep_color
== 125)
750 if (pclk
== 27027 || pclk
== 74250)
751 deep_color_correct
= true;
752 if (deep_color
== 150)
754 deep_color_correct
= true;
759 if (deep_color
== 125)
761 deep_color_correct
= true;
767 if (deep_color_correct
) {
768 switch (sample_freq
) {
794 switch (sample_freq
) {
820 /* Calculate CTS. See HDMI 1.3a or 1.4a specifications */
821 *cts
= pclk
* (*n
/ 128) * deep_color
/ (sample_freq
/ 10);
826 int hdmi_audio_enable(void)
828 DSSDBG("audio_enable\n");
830 return hdmi
.ip_data
.ops
->audio_enable(&hdmi
.ip_data
);
833 void hdmi_audio_disable(void)
835 DSSDBG("audio_disable\n");
837 hdmi
.ip_data
.ops
->audio_disable(&hdmi
.ip_data
);
840 int hdmi_audio_start(void)
842 DSSDBG("audio_start\n");
844 return hdmi
.ip_data
.ops
->audio_start(&hdmi
.ip_data
);
847 void hdmi_audio_stop(void)
849 DSSDBG("audio_stop\n");
851 hdmi
.ip_data
.ops
->audio_stop(&hdmi
.ip_data
);
854 bool hdmi_mode_has_audio(void)
856 if (hdmi
.ip_data
.cfg
.cm
.mode
== HDMI_HDMI
)
862 int hdmi_audio_config(struct omap_dss_audio
*audio
)
864 return hdmi
.ip_data
.ops
->audio_config(&hdmi
.ip_data
, audio
);
869 static void __init
hdmi_probe_pdata(struct platform_device
*pdev
)
871 struct omap_dss_board_info
*pdata
= pdev
->dev
.platform_data
;
874 for (i
= 0; i
< pdata
->num_devices
; ++i
) {
875 struct omap_dss_device
*dssdev
= pdata
->devices
[i
];
877 if (dssdev
->type
!= OMAP_DISPLAY_TYPE_HDMI
)
880 r
= hdmi_init_display(dssdev
);
882 DSSERR("device %s init failed: %d\n", dssdev
->name
, r
);
886 r
= omap_dss_register_device(dssdev
, &pdev
->dev
, i
);
888 DSSERR("device %s register failed: %d\n",
893 /* HDMI HW IP initialisation */
894 static int __init
omapdss_hdmihw_probe(struct platform_device
*pdev
)
896 struct resource
*hdmi_mem
;
901 mutex_init(&hdmi
.lock
);
903 hdmi_mem
= platform_get_resource(hdmi
.pdev
, IORESOURCE_MEM
, 0);
905 DSSERR("can't get IORESOURCE_MEM HDMI\n");
909 /* Base address taken from platform */
910 hdmi
.ip_data
.base_wp
= ioremap(hdmi_mem
->start
,
911 resource_size(hdmi_mem
));
912 if (!hdmi
.ip_data
.base_wp
) {
913 DSSERR("can't ioremap WP\n");
917 r
= hdmi_get_clocks(pdev
);
919 iounmap(hdmi
.ip_data
.base_wp
);
923 pm_runtime_enable(&pdev
->dev
);
925 hdmi
.ip_data
.core_sys_offset
= HDMI_CORE_SYS
;
926 hdmi
.ip_data
.core_av_offset
= HDMI_CORE_AV
;
927 hdmi
.ip_data
.pll_offset
= HDMI_PLLCTRL
;
928 hdmi
.ip_data
.phy_offset
= HDMI_PHY
;
930 mutex_init(&hdmi
.ip_data
.lock
);
934 dss_debugfs_create_file("hdmi", hdmi_dump_regs
);
936 hdmi_probe_pdata(pdev
);
941 static int __exit
omapdss_hdmihw_remove(struct platform_device
*pdev
)
943 omap_dss_unregister_child_devices(&pdev
->dev
);
947 pm_runtime_disable(&pdev
->dev
);
951 iounmap(hdmi
.ip_data
.base_wp
);
956 static int hdmi_runtime_suspend(struct device
*dev
)
958 clk_disable_unprepare(hdmi
.sys_clk
);
965 static int hdmi_runtime_resume(struct device
*dev
)
969 r
= dispc_runtime_get();
973 clk_prepare_enable(hdmi
.sys_clk
);
978 static const struct dev_pm_ops hdmi_pm_ops
= {
979 .runtime_suspend
= hdmi_runtime_suspend
,
980 .runtime_resume
= hdmi_runtime_resume
,
983 static struct platform_driver omapdss_hdmihw_driver
= {
984 .remove
= __exit_p(omapdss_hdmihw_remove
),
986 .name
= "omapdss_hdmi",
987 .owner
= THIS_MODULE
,
992 int __init
hdmi_init_platform_driver(void)
994 return platform_driver_probe(&omapdss_hdmihw_driver
, omapdss_hdmihw_probe
);
997 void __exit
hdmi_uninit_platform_driver(void)
999 platform_driver_unregister(&omapdss_hdmihw_driver
);