diff options
Diffstat (limited to 'arch/arm/mach-omap2/display.c')
-rw-r--r-- | arch/arm/mach-omap2/display.c | 148 |
1 files changed, 148 insertions, 0 deletions
diff --git a/arch/arm/mach-omap2/display.c b/arch/arm/mach-omap2/display.c new file mode 100644 index 000000000000..543fcb8b518c --- /dev/null +++ b/arch/arm/mach-omap2/display.c | |||
@@ -0,0 +1,148 @@ | |||
1 | /* | ||
2 | * OMAP2plus display device setup / initialization. | ||
3 | * | ||
4 | * Copyright (C) 2010 Texas Instruments Incorporated - http://www.ti.com/ | ||
5 | * Senthilvadivu Guruswamy | ||
6 | * Sumit Semwal | ||
7 | * | ||
8 | * This program is free software; you can redistribute it and/or modify | ||
9 | * it under the terms of the GNU General Public License version 2 as | ||
10 | * published by the Free Software Foundation. | ||
11 | * | ||
12 | * This program is distributed "as is" WITHOUT ANY WARRANTY of any | ||
13 | * kind, whether express or implied; without even the implied warranty | ||
14 | * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
15 | * GNU General Public License for more details. | ||
16 | */ | ||
17 | |||
18 | #include <linux/kernel.h> | ||
19 | #include <linux/init.h> | ||
20 | #include <linux/platform_device.h> | ||
21 | #include <linux/io.h> | ||
22 | #include <linux/clk.h> | ||
23 | #include <linux/err.h> | ||
24 | |||
25 | #include <video/omapdss.h> | ||
26 | #include <plat/omap_hwmod.h> | ||
27 | #include <plat/omap_device.h> | ||
28 | |||
29 | static struct platform_device omap_display_device = { | ||
30 | .name = "omapdss", | ||
31 | .id = -1, | ||
32 | .dev = { | ||
33 | .platform_data = NULL, | ||
34 | }, | ||
35 | }; | ||
36 | |||
37 | static struct omap_device_pm_latency omap_dss_latency[] = { | ||
38 | [0] = { | ||
39 | .deactivate_func = omap_device_idle_hwmods, | ||
40 | .activate_func = omap_device_enable_hwmods, | ||
41 | .flags = OMAP_DEVICE_LATENCY_AUTO_ADJUST, | ||
42 | }, | ||
43 | }; | ||
44 | |||
45 | /* oh_core is used for getting opt-clocks */ | ||
46 | static struct omap_hwmod *oh_core; | ||
47 | |||
48 | static bool opt_clock_available(const char *clk_role) | ||
49 | { | ||
50 | int i; | ||
51 | |||
52 | for (i = 0; i < oh_core->opt_clks_cnt; i++) { | ||
53 | if (!strcmp(oh_core->opt_clks[i].role, clk_role)) | ||
54 | return true; | ||
55 | } | ||
56 | return false; | ||
57 | } | ||
58 | |||
59 | struct omap_dss_hwmod_data { | ||
60 | const char *oh_name; | ||
61 | const char *dev_name; | ||
62 | const int id; | ||
63 | }; | ||
64 | |||
65 | static const struct omap_dss_hwmod_data omap2_dss_hwmod_data[] __initdata = { | ||
66 | { "dss_core", "omapdss_dss", -1 }, | ||
67 | { "dss_dispc", "omapdss_dispc", -1 }, | ||
68 | { "dss_rfbi", "omapdss_rfbi", -1 }, | ||
69 | { "dss_venc", "omapdss_venc", -1 }, | ||
70 | }; | ||
71 | |||
72 | static const struct omap_dss_hwmod_data omap3_dss_hwmod_data[] __initdata = { | ||
73 | { "dss_core", "omapdss_dss", -1 }, | ||
74 | { "dss_dispc", "omapdss_dispc", -1 }, | ||
75 | { "dss_rfbi", "omapdss_rfbi", -1 }, | ||
76 | { "dss_venc", "omapdss_venc", -1 }, | ||
77 | { "dss_dsi1", "omapdss_dsi1", -1 }, | ||
78 | }; | ||
79 | |||
80 | static const struct omap_dss_hwmod_data omap4_dss_hwmod_data[] __initdata = { | ||
81 | { "dss_core", "omapdss_dss", -1 }, | ||
82 | { "dss_dispc", "omapdss_dispc", -1 }, | ||
83 | { "dss_rfbi", "omapdss_rfbi", -1 }, | ||
84 | { "dss_venc", "omapdss_venc", -1 }, | ||
85 | { "dss_dsi1", "omapdss_dsi1", -1 }, | ||
86 | { "dss_dsi2", "omapdss_dsi2", -1 }, | ||
87 | { "dss_hdmi", "omapdss_hdmi", -1 }, | ||
88 | }; | ||
89 | |||
90 | int __init omap_display_init(struct omap_dss_board_info *board_data) | ||
91 | { | ||
92 | int r = 0; | ||
93 | struct omap_hwmod *oh; | ||
94 | struct omap_device *od; | ||
95 | int i, oh_count; | ||
96 | struct omap_display_platform_data pdata; | ||
97 | const struct omap_dss_hwmod_data *curr_dss_hwmod; | ||
98 | |||
99 | memset(&pdata, 0, sizeof(pdata)); | ||
100 | |||
101 | if (cpu_is_omap24xx()) { | ||
102 | curr_dss_hwmod = omap2_dss_hwmod_data; | ||
103 | oh_count = ARRAY_SIZE(omap2_dss_hwmod_data); | ||
104 | } else if (cpu_is_omap34xx()) { | ||
105 | curr_dss_hwmod = omap3_dss_hwmod_data; | ||
106 | oh_count = ARRAY_SIZE(omap3_dss_hwmod_data); | ||
107 | } else { | ||
108 | curr_dss_hwmod = omap4_dss_hwmod_data; | ||
109 | oh_count = ARRAY_SIZE(omap4_dss_hwmod_data); | ||
110 | } | ||
111 | |||
112 | /* opt_clks are always associated with dss hwmod */ | ||
113 | oh_core = omap_hwmod_lookup("dss_core"); | ||
114 | if (!oh_core) { | ||
115 | pr_err("Could not look up dss_core.\n"); | ||
116 | return -ENODEV; | ||
117 | } | ||
118 | |||
119 | pdata.board_data = board_data; | ||
120 | pdata.board_data->get_last_off_on_transaction_id = NULL; | ||
121 | pdata.opt_clock_available = opt_clock_available; | ||
122 | |||
123 | for (i = 0; i < oh_count; i++) { | ||
124 | oh = omap_hwmod_lookup(curr_dss_hwmod[i].oh_name); | ||
125 | if (!oh) { | ||
126 | pr_err("Could not look up %s\n", | ||
127 | curr_dss_hwmod[i].oh_name); | ||
128 | return -ENODEV; | ||
129 | } | ||
130 | |||
131 | od = omap_device_build(curr_dss_hwmod[i].dev_name, | ||
132 | curr_dss_hwmod[i].id, oh, &pdata, | ||
133 | sizeof(struct omap_display_platform_data), | ||
134 | omap_dss_latency, | ||
135 | ARRAY_SIZE(omap_dss_latency), 0); | ||
136 | |||
137 | if (WARN((IS_ERR(od)), "Could not build omap_device for %s\n", | ||
138 | curr_dss_hwmod[i].oh_name)) | ||
139 | return -ENODEV; | ||
140 | } | ||
141 | omap_display_device.dev.platform_data = board_data; | ||
142 | |||
143 | r = platform_device_register(&omap_display_device); | ||
144 | if (r < 0) | ||
145 | printk(KERN_ERR "Unable to register OMAP-Display device\n"); | ||
146 | |||
147 | return r; | ||
148 | } | ||