diff options
Diffstat (limited to 'drivers/video/fbdev/omap2/omapfb/dss/output.c')
-rw-r--r-- | drivers/video/fbdev/omap2/omapfb/dss/output.c | 267 |
1 files changed, 267 insertions, 0 deletions
diff --git a/drivers/video/fbdev/omap2/omapfb/dss/output.c b/drivers/video/fbdev/omap2/omapfb/dss/output.c new file mode 100644 index 000000000000..16072159bd24 --- /dev/null +++ b/drivers/video/fbdev/omap2/omapfb/dss/output.c | |||
@@ -0,0 +1,267 @@ | |||
1 | /* | ||
2 | * Copyright (C) 2012 Texas Instruments Ltd | ||
3 | * Author: Archit Taneja <archit@ti.com> | ||
4 | * | ||
5 | * This program is free software; you can redistribute it and/or modify it | ||
6 | * under the terms of the GNU General Public License version 2 as published by | ||
7 | * the Free Software Foundation. | ||
8 | * | ||
9 | * This program is distributed in the hope that it will be useful, but WITHOUT | ||
10 | * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or | ||
11 | * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for | ||
12 | * more details. | ||
13 | * | ||
14 | * You should have received a copy of the GNU General Public License along with | ||
15 | * this program. If not, see <http://www.gnu.org/licenses/>. | ||
16 | */ | ||
17 | |||
18 | #include <linux/kernel.h> | ||
19 | #include <linux/module.h> | ||
20 | #include <linux/platform_device.h> | ||
21 | #include <linux/slab.h> | ||
22 | #include <linux/of.h> | ||
23 | |||
24 | #include <video/omapdss.h> | ||
25 | |||
26 | #include "dss.h" | ||
27 | |||
28 | static LIST_HEAD(output_list); | ||
29 | static DEFINE_MUTEX(output_lock); | ||
30 | |||
31 | int omapdss_output_set_device(struct omap_dss_device *out, | ||
32 | struct omap_dss_device *dssdev) | ||
33 | { | ||
34 | int r; | ||
35 | |||
36 | mutex_lock(&output_lock); | ||
37 | |||
38 | if (out->dst) { | ||
39 | DSSERR("output already has device %s connected to it\n", | ||
40 | out->dst->name); | ||
41 | r = -EINVAL; | ||
42 | goto err; | ||
43 | } | ||
44 | |||
45 | if (out->output_type != dssdev->type) { | ||
46 | DSSERR("output type and display type don't match\n"); | ||
47 | r = -EINVAL; | ||
48 | goto err; | ||
49 | } | ||
50 | |||
51 | out->dst = dssdev; | ||
52 | dssdev->src = out; | ||
53 | |||
54 | mutex_unlock(&output_lock); | ||
55 | |||
56 | return 0; | ||
57 | err: | ||
58 | mutex_unlock(&output_lock); | ||
59 | |||
60 | return r; | ||
61 | } | ||
62 | EXPORT_SYMBOL(omapdss_output_set_device); | ||
63 | |||
64 | int omapdss_output_unset_device(struct omap_dss_device *out) | ||
65 | { | ||
66 | int r; | ||
67 | |||
68 | mutex_lock(&output_lock); | ||
69 | |||
70 | if (!out->dst) { | ||
71 | DSSERR("output doesn't have a device connected to it\n"); | ||
72 | r = -EINVAL; | ||
73 | goto err; | ||
74 | } | ||
75 | |||
76 | if (out->dst->state != OMAP_DSS_DISPLAY_DISABLED) { | ||
77 | DSSERR("device %s is not disabled, cannot unset device\n", | ||
78 | out->dst->name); | ||
79 | r = -EINVAL; | ||
80 | goto err; | ||
81 | } | ||
82 | |||
83 | out->dst->src = NULL; | ||
84 | out->dst = NULL; | ||
85 | |||
86 | mutex_unlock(&output_lock); | ||
87 | |||
88 | return 0; | ||
89 | err: | ||
90 | mutex_unlock(&output_lock); | ||
91 | |||
92 | return r; | ||
93 | } | ||
94 | EXPORT_SYMBOL(omapdss_output_unset_device); | ||
95 | |||
96 | int omapdss_register_output(struct omap_dss_device *out) | ||
97 | { | ||
98 | list_add_tail(&out->list, &output_list); | ||
99 | return 0; | ||
100 | } | ||
101 | EXPORT_SYMBOL(omapdss_register_output); | ||
102 | |||
103 | void omapdss_unregister_output(struct omap_dss_device *out) | ||
104 | { | ||
105 | list_del(&out->list); | ||
106 | } | ||
107 | EXPORT_SYMBOL(omapdss_unregister_output); | ||
108 | |||
109 | struct omap_dss_device *omap_dss_get_output(enum omap_dss_output_id id) | ||
110 | { | ||
111 | struct omap_dss_device *out; | ||
112 | |||
113 | list_for_each_entry(out, &output_list, list) { | ||
114 | if (out->id == id) | ||
115 | return out; | ||
116 | } | ||
117 | |||
118 | return NULL; | ||
119 | } | ||
120 | EXPORT_SYMBOL(omap_dss_get_output); | ||
121 | |||
122 | struct omap_dss_device *omap_dss_find_output(const char *name) | ||
123 | { | ||
124 | struct omap_dss_device *out; | ||
125 | |||
126 | list_for_each_entry(out, &output_list, list) { | ||
127 | if (strcmp(out->name, name) == 0) | ||
128 | return omap_dss_get_device(out); | ||
129 | } | ||
130 | |||
131 | return NULL; | ||
132 | } | ||
133 | EXPORT_SYMBOL(omap_dss_find_output); | ||
134 | |||
135 | struct omap_dss_device *omap_dss_find_output_by_port_node(struct device_node *port) | ||
136 | { | ||
137 | struct device_node *src_node; | ||
138 | struct omap_dss_device *out; | ||
139 | u32 reg; | ||
140 | |||
141 | src_node = dss_of_port_get_parent_device(port); | ||
142 | if (!src_node) | ||
143 | return NULL; | ||
144 | |||
145 | reg = dss_of_port_get_port_number(port); | ||
146 | |||
147 | list_for_each_entry(out, &output_list, list) { | ||
148 | if (out->dev->of_node == src_node && out->port_num == reg) { | ||
149 | of_node_put(src_node); | ||
150 | return omap_dss_get_device(out); | ||
151 | } | ||
152 | } | ||
153 | |||
154 | of_node_put(src_node); | ||
155 | |||
156 | return NULL; | ||
157 | } | ||
158 | EXPORT_SYMBOL(omap_dss_find_output_by_port_node); | ||
159 | |||
160 | struct omap_dss_device *omapdss_find_output_from_display(struct omap_dss_device *dssdev) | ||
161 | { | ||
162 | while (dssdev->src) | ||
163 | dssdev = dssdev->src; | ||
164 | |||
165 | if (dssdev->id != 0) | ||
166 | return omap_dss_get_device(dssdev); | ||
167 | |||
168 | return NULL; | ||
169 | } | ||
170 | EXPORT_SYMBOL(omapdss_find_output_from_display); | ||
171 | |||
172 | struct omap_overlay_manager *omapdss_find_mgr_from_display(struct omap_dss_device *dssdev) | ||
173 | { | ||
174 | struct omap_dss_device *out; | ||
175 | struct omap_overlay_manager *mgr; | ||
176 | |||
177 | out = omapdss_find_output_from_display(dssdev); | ||
178 | |||
179 | if (out == NULL) | ||
180 | return NULL; | ||
181 | |||
182 | mgr = out->manager; | ||
183 | |||
184 | omap_dss_put_device(out); | ||
185 | |||
186 | return mgr; | ||
187 | } | ||
188 | EXPORT_SYMBOL(omapdss_find_mgr_from_display); | ||
189 | |||
190 | static const struct dss_mgr_ops *dss_mgr_ops; | ||
191 | |||
192 | int dss_install_mgr_ops(const struct dss_mgr_ops *mgr_ops) | ||
193 | { | ||
194 | if (dss_mgr_ops) | ||
195 | return -EBUSY; | ||
196 | |||
197 | dss_mgr_ops = mgr_ops; | ||
198 | |||
199 | return 0; | ||
200 | } | ||
201 | EXPORT_SYMBOL(dss_install_mgr_ops); | ||
202 | |||
203 | void dss_uninstall_mgr_ops(void) | ||
204 | { | ||
205 | dss_mgr_ops = NULL; | ||
206 | } | ||
207 | EXPORT_SYMBOL(dss_uninstall_mgr_ops); | ||
208 | |||
209 | int dss_mgr_connect(struct omap_overlay_manager *mgr, | ||
210 | struct omap_dss_device *dst) | ||
211 | { | ||
212 | return dss_mgr_ops->connect(mgr, dst); | ||
213 | } | ||
214 | EXPORT_SYMBOL(dss_mgr_connect); | ||
215 | |||
216 | void dss_mgr_disconnect(struct omap_overlay_manager *mgr, | ||
217 | struct omap_dss_device *dst) | ||
218 | { | ||
219 | dss_mgr_ops->disconnect(mgr, dst); | ||
220 | } | ||
221 | EXPORT_SYMBOL(dss_mgr_disconnect); | ||
222 | |||
223 | void dss_mgr_set_timings(struct omap_overlay_manager *mgr, | ||
224 | const struct omap_video_timings *timings) | ||
225 | { | ||
226 | dss_mgr_ops->set_timings(mgr, timings); | ||
227 | } | ||
228 | EXPORT_SYMBOL(dss_mgr_set_timings); | ||
229 | |||
230 | void dss_mgr_set_lcd_config(struct omap_overlay_manager *mgr, | ||
231 | const struct dss_lcd_mgr_config *config) | ||
232 | { | ||
233 | dss_mgr_ops->set_lcd_config(mgr, config); | ||
234 | } | ||
235 | EXPORT_SYMBOL(dss_mgr_set_lcd_config); | ||
236 | |||
237 | int dss_mgr_enable(struct omap_overlay_manager *mgr) | ||
238 | { | ||
239 | return dss_mgr_ops->enable(mgr); | ||
240 | } | ||
241 | EXPORT_SYMBOL(dss_mgr_enable); | ||
242 | |||
243 | void dss_mgr_disable(struct omap_overlay_manager *mgr) | ||
244 | { | ||
245 | dss_mgr_ops->disable(mgr); | ||
246 | } | ||
247 | EXPORT_SYMBOL(dss_mgr_disable); | ||
248 | |||
249 | void dss_mgr_start_update(struct omap_overlay_manager *mgr) | ||
250 | { | ||
251 | dss_mgr_ops->start_update(mgr); | ||
252 | } | ||
253 | EXPORT_SYMBOL(dss_mgr_start_update); | ||
254 | |||
255 | int dss_mgr_register_framedone_handler(struct omap_overlay_manager *mgr, | ||
256 | void (*handler)(void *), void *data) | ||
257 | { | ||
258 | return dss_mgr_ops->register_framedone_handler(mgr, handler, data); | ||
259 | } | ||
260 | EXPORT_SYMBOL(dss_mgr_register_framedone_handler); | ||
261 | |||
262 | void dss_mgr_unregister_framedone_handler(struct omap_overlay_manager *mgr, | ||
263 | void (*handler)(void *), void *data) | ||
264 | { | ||
265 | dss_mgr_ops->unregister_framedone_handler(mgr, handler, data); | ||
266 | } | ||
267 | EXPORT_SYMBOL(dss_mgr_unregister_framedone_handler); | ||