Rev 6084 | Go to most recent revision | Only display areas with differences | Regard whitespace | Details | Blame | Last modification | View Log | RSS feed
Rev 6084 | Rev 6937 | ||
---|---|---|---|
1 | /* |
1 | /* |
2 | * Copyright (c) 2014 Samsung Electronics Co., Ltd |
2 | * Copyright (c) 2014 Samsung Electronics Co., Ltd |
3 | * |
3 | * |
4 | * Permission is hereby granted, free of charge, to any person obtaining a |
4 | * Permission is hereby granted, free of charge, to any person obtaining a |
5 | * copy of this software and associated documentation files (the "Software"), |
5 | * copy of this software and associated documentation files (the "Software"), |
6 | * to deal in the Software without restriction, including without limitation |
6 | * to deal in the Software without restriction, including without limitation |
7 | * the rights to use, copy, modify, merge, publish, distribute, sub license, |
7 | * the rights to use, copy, modify, merge, publish, distribute, sub license, |
8 | * and/or sell copies of the Software, and to permit persons to whom the |
8 | * and/or sell copies of the Software, and to permit persons to whom the |
9 | * Software is furnished to do so, subject to the following conditions: |
9 | * Software is furnished to do so, subject to the following conditions: |
10 | * |
10 | * |
11 | * The above copyright notice and this permission notice (including the |
11 | * The above copyright notice and this permission notice (including the |
12 | * next paragraph) shall be included in all copies or substantial portions |
12 | * next paragraph) shall be included in all copies or substantial portions |
13 | * of the Software. |
13 | * of the Software. |
14 | * |
14 | * |
15 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR |
15 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR |
16 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, |
16 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, |
17 | * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL |
17 | * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL |
18 | * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER |
18 | * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER |
19 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING |
19 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING |
20 | * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER |
20 | * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER |
21 | * DEALINGS IN THE SOFTWARE. |
21 | * DEALINGS IN THE SOFTWARE. |
22 | */ |
22 | */ |
23 | 23 | ||
24 | #include |
24 | #include |
25 | #include |
25 | #include |
26 | 26 | ||
27 | #include |
27 | #include |
28 | 28 | ||
29 | #include "drm/drmP.h" |
29 | #include "drm/drmP.h" |
30 | 30 | ||
31 | /** |
31 | /** |
32 | * DOC: overview |
32 | * DOC: overview |
33 | * |
33 | * |
34 | * drm_bridge represents a device that hangs on to an encoder. These are handy |
34 | * struct &drm_bridge represents a device that hangs on to an encoder. These are |
35 | * when a regular drm_encoder entity isn't enough to represent the entire |
35 | * handy when a regular &drm_encoder entity isn't enough to represent the entire |
36 | * encoder chain. |
36 | * encoder chain. |
37 | * |
37 | * |
38 | * A bridge is always associated to a single drm_encoder at a time, but can be |
38 | * A bridge is always attached to a single &drm_encoder at a time, but can be |
39 | * either connected to it directly, or through an intermediate bridge: |
39 | * either connected to it directly, or through an intermediate bridge: |
40 | * |
40 | * |
41 | * encoder ---> bridge B ---> bridge A |
41 | * encoder ---> bridge B ---> bridge A |
42 | * |
42 | * |
43 | * Here, the output of the encoder feeds to bridge B, and that furthers feeds to |
43 | * Here, the output of the encoder feeds to bridge B, and that furthers feeds to |
44 | * bridge A. |
44 | * bridge A. |
45 | * |
45 | * |
46 | * The driver using the bridge is responsible to make the associations between |
46 | * The driver using the bridge is responsible to make the associations between |
47 | * the encoder and bridges. Once these links are made, the bridges will |
47 | * the encoder and bridges. Once these links are made, the bridges will |
48 | * participate along with encoder functions to perform mode_set/enable/disable |
48 | * participate along with encoder functions to perform mode_set/enable/disable |
49 | * through the ops provided in drm_bridge_funcs. |
49 | * through the ops provided in &drm_bridge_funcs. |
50 | * |
50 | * |
51 | * drm_bridge, like drm_panel, aren't drm_mode_object entities like planes, |
51 | * drm_bridge, like drm_panel, aren't drm_mode_object entities like planes, |
52 | * crtcs, encoders or connectors. They just provide additional hooks to get the |
52 | * CRTCs, encoders or connectors and hence are not visible to userspace. They |
53 | * desired output at the end of the encoder chain. |
53 | * just provide additional hooks to get the desired output at the end of the |
- | 54 | * encoder chain. |
|
- | 55 | * |
|
- | 56 | * Bridges can also be chained up using the next pointer in struct &drm_bridge. |
|
- | 57 | * |
|
- | 58 | * Both legacy CRTC helpers and the new atomic modeset helpers support bridges. |
|
54 | */ |
59 | */ |
55 | 60 | ||
56 | static DEFINE_MUTEX(bridge_lock); |
61 | static DEFINE_MUTEX(bridge_lock); |
57 | static LIST_HEAD(bridge_list); |
62 | static LIST_HEAD(bridge_list); |
58 | 63 | ||
59 | /** |
64 | /** |
60 | * drm_bridge_add - add the given bridge to the global bridge list |
65 | * drm_bridge_add - add the given bridge to the global bridge list |
61 | * |
66 | * |
62 | * @bridge: bridge control structure |
67 | * @bridge: bridge control structure |
63 | * |
68 | * |
64 | * RETURNS: |
69 | * RETURNS: |
65 | * Unconditionally returns Zero. |
70 | * Unconditionally returns Zero. |
66 | */ |
71 | */ |
67 | int drm_bridge_add(struct drm_bridge *bridge) |
72 | int drm_bridge_add(struct drm_bridge *bridge) |
68 | { |
73 | { |
69 | mutex_lock(&bridge_lock); |
74 | mutex_lock(&bridge_lock); |
70 | list_add_tail(&bridge->list, &bridge_list); |
75 | list_add_tail(&bridge->list, &bridge_list); |
71 | mutex_unlock(&bridge_lock); |
76 | mutex_unlock(&bridge_lock); |
72 | 77 | ||
73 | return 0; |
78 | return 0; |
74 | } |
79 | } |
75 | EXPORT_SYMBOL(drm_bridge_add); |
80 | EXPORT_SYMBOL(drm_bridge_add); |
76 | 81 | ||
77 | /** |
82 | /** |
78 | * drm_bridge_remove - remove the given bridge from the global bridge list |
83 | * drm_bridge_remove - remove the given bridge from the global bridge list |
79 | * |
84 | * |
80 | * @bridge: bridge control structure |
85 | * @bridge: bridge control structure |
81 | */ |
86 | */ |
82 | void drm_bridge_remove(struct drm_bridge *bridge) |
87 | void drm_bridge_remove(struct drm_bridge *bridge) |
83 | { |
88 | { |
84 | mutex_lock(&bridge_lock); |
89 | mutex_lock(&bridge_lock); |
85 | list_del_init(&bridge->list); |
90 | list_del_init(&bridge->list); |
86 | mutex_unlock(&bridge_lock); |
91 | mutex_unlock(&bridge_lock); |
87 | } |
92 | } |
88 | EXPORT_SYMBOL(drm_bridge_remove); |
93 | EXPORT_SYMBOL(drm_bridge_remove); |
89 | 94 | ||
90 | /** |
95 | /** |
91 | * drm_bridge_attach - associate given bridge to our DRM device |
96 | * drm_bridge_attach - associate given bridge to our DRM device |
92 | * |
97 | * |
93 | * @dev: DRM device |
98 | * @dev: DRM device |
94 | * @bridge: bridge control structure |
99 | * @bridge: bridge control structure |
95 | * |
100 | * |
96 | * called by a kms driver to link one of our encoder/bridge to the given |
101 | * called by a kms driver to link one of our encoder/bridge to the given |
97 | * bridge. |
102 | * bridge. |
98 | * |
103 | * |
99 | * Note that setting up links between the bridge and our encoder/bridge |
104 | * Note that setting up links between the bridge and our encoder/bridge |
100 | * objects needs to be handled by the kms driver itself |
105 | * objects needs to be handled by the kms driver itself |
101 | * |
106 | * |
102 | * RETURNS: |
107 | * RETURNS: |
103 | * Zero on success, error code on failure |
108 | * Zero on success, error code on failure |
104 | */ |
109 | */ |
105 | int drm_bridge_attach(struct drm_device *dev, struct drm_bridge *bridge) |
110 | int drm_bridge_attach(struct drm_device *dev, struct drm_bridge *bridge) |
106 | { |
111 | { |
107 | if (!dev || !bridge) |
112 | if (!dev || !bridge) |
108 | return -EINVAL; |
113 | return -EINVAL; |
109 | 114 | ||
110 | if (bridge->dev) |
115 | if (bridge->dev) |
111 | return -EBUSY; |
116 | return -EBUSY; |
112 | 117 | ||
113 | bridge->dev = dev; |
118 | bridge->dev = dev; |
114 | 119 | ||
115 | if (bridge->funcs->attach) |
120 | if (bridge->funcs->attach) |
116 | return bridge->funcs->attach(bridge); |
121 | return bridge->funcs->attach(bridge); |
117 | 122 | ||
118 | return 0; |
123 | return 0; |
119 | } |
124 | } |
120 | EXPORT_SYMBOL(drm_bridge_attach); |
125 | EXPORT_SYMBOL(drm_bridge_attach); |
121 | 126 | ||
122 | /** |
127 | /** |
123 | * DOC: bridge callbacks |
128 | * DOC: bridge callbacks |
124 | * |
129 | * |
125 | * The drm_bridge_funcs ops are populated by the bridge driver. The drm |
130 | * The &drm_bridge_funcs ops are populated by the bridge driver. The DRM |
126 | * internals(atomic and crtc helpers) use the helpers defined in drm_bridge.c |
131 | * internals (atomic and CRTC helpers) use the helpers defined in drm_bridge.c |
127 | * These helpers call a specific drm_bridge_funcs op for all the bridges |
132 | * These helpers call a specific &drm_bridge_funcs op for all the bridges |
128 | * during encoder configuration. |
133 | * during encoder configuration. |
129 | * |
134 | * |
130 | * When creating a bridge driver, one can implement drm_bridge_funcs op with |
- | |
131 | * the help of these rough rules: |
- | |
132 | * |
- | |
133 | * pre_enable: this contains things needed to be done for the bridge before |
- | |
134 | * its clock and timings are enabled by its source. For a bridge, its source |
- | |
135 | * is generally the encoder or bridge just before it in the encoder chain. |
- | |
136 | * |
- | |
137 | * enable: this contains things needed to be done for the bridge once its |
- | |
138 | * source is enabled. In other words, enable is called once the source is |
- | |
139 | * ready with clock and timing needed by the bridge. |
- | |
140 | * |
- | |
141 | * disable: this contains things needed to be done for the bridge assuming |
- | |
142 | * that its source is still enabled, i.e. clock and timings are still on. |
- | |
143 | * |
- | |
144 | * post_disable: this contains things needed to be done for the bridge once |
- | |
145 | * its source is disabled, i.e. once clocks and timings are off. |
- | |
146 | * |
- | |
147 | * mode_fixup: this should fixup the given mode for the bridge. It is called |
- | |
148 | * after the encoder's mode fixup. mode_fixup can also reject a mode completely |
- | |
149 | * if it's unsuitable for the hardware. |
- | |
150 | * |
- | |
151 | * mode_set: this sets up the mode for the bridge. It assumes that its source |
135 | * For detailed specification of the bridge callbacks see &drm_bridge_funcs. |
152 | * (an encoder or a bridge) has set the mode too. |
- | |
153 | */ |
136 | */ |
154 | 137 | ||
155 | /** |
138 | /** |
156 | * drm_bridge_mode_fixup - fixup proposed mode for all bridges in the |
139 | * drm_bridge_mode_fixup - fixup proposed mode for all bridges in the |
157 | * encoder chain |
140 | * encoder chain |
158 | * @bridge: bridge control structure |
141 | * @bridge: bridge control structure |
159 | * @mode: desired mode to be set for the bridge |
142 | * @mode: desired mode to be set for the bridge |
160 | * @adjusted_mode: updated mode that works for this bridge |
143 | * @adjusted_mode: updated mode that works for this bridge |
161 | * |
144 | * |
162 | * Calls 'mode_fixup' drm_bridge_funcs op for all the bridges in the |
145 | * Calls ->mode_fixup() &drm_bridge_funcs op for all the bridges in the |
163 | * encoder chain, starting from the first bridge to the last. |
146 | * encoder chain, starting from the first bridge to the last. |
164 | * |
147 | * |
165 | * Note: the bridge passed should be the one closest to the encoder |
148 | * Note: the bridge passed should be the one closest to the encoder |
166 | * |
149 | * |
167 | * RETURNS: |
150 | * RETURNS: |
168 | * true on success, false on failure |
151 | * true on success, false on failure |
169 | */ |
152 | */ |
170 | bool drm_bridge_mode_fixup(struct drm_bridge *bridge, |
153 | bool drm_bridge_mode_fixup(struct drm_bridge *bridge, |
171 | const struct drm_display_mode *mode, |
154 | const struct drm_display_mode *mode, |
172 | struct drm_display_mode *adjusted_mode) |
155 | struct drm_display_mode *adjusted_mode) |
173 | { |
156 | { |
174 | bool ret = true; |
157 | bool ret = true; |
175 | 158 | ||
176 | if (!bridge) |
159 | if (!bridge) |
177 | return true; |
160 | return true; |
178 | 161 | ||
179 | if (bridge->funcs->mode_fixup) |
162 | if (bridge->funcs->mode_fixup) |
180 | ret = bridge->funcs->mode_fixup(bridge, mode, adjusted_mode); |
163 | ret = bridge->funcs->mode_fixup(bridge, mode, adjusted_mode); |
181 | 164 | ||
182 | ret = ret && drm_bridge_mode_fixup(bridge->next, mode, adjusted_mode); |
165 | ret = ret && drm_bridge_mode_fixup(bridge->next, mode, adjusted_mode); |
183 | 166 | ||
184 | return ret; |
167 | return ret; |
185 | } |
168 | } |
186 | EXPORT_SYMBOL(drm_bridge_mode_fixup); |
169 | EXPORT_SYMBOL(drm_bridge_mode_fixup); |
187 | 170 | ||
188 | /** |
171 | /** |
189 | * drm_bridge_disable - calls 'disable' drm_bridge_funcs op for all |
172 | * drm_bridge_disable - calls ->disable() &drm_bridge_funcs op for all |
190 | * bridges in the encoder chain. |
173 | * bridges in the encoder chain. |
191 | * @bridge: bridge control structure |
174 | * @bridge: bridge control structure |
192 | * |
175 | * |
193 | * Calls 'disable' drm_bridge_funcs op for all the bridges in the encoder |
176 | * Calls ->disable() &drm_bridge_funcs op for all the bridges in the encoder |
194 | * chain, starting from the last bridge to the first. These are called before |
177 | * chain, starting from the last bridge to the first. These are called before |
195 | * calling the encoder's prepare op. |
178 | * calling the encoder's prepare op. |
196 | * |
179 | * |
197 | * Note: the bridge passed should be the one closest to the encoder |
180 | * Note: the bridge passed should be the one closest to the encoder |
198 | */ |
181 | */ |
199 | void drm_bridge_disable(struct drm_bridge *bridge) |
182 | void drm_bridge_disable(struct drm_bridge *bridge) |
200 | { |
183 | { |
201 | if (!bridge) |
184 | if (!bridge) |
202 | return; |
185 | return; |
203 | 186 | ||
204 | drm_bridge_disable(bridge->next); |
187 | drm_bridge_disable(bridge->next); |
205 | 188 | ||
206 | bridge->funcs->disable(bridge); |
189 | bridge->funcs->disable(bridge); |
207 | } |
190 | } |
208 | EXPORT_SYMBOL(drm_bridge_disable); |
191 | EXPORT_SYMBOL(drm_bridge_disable); |
209 | 192 | ||
210 | /** |
193 | /** |
211 | * drm_bridge_post_disable - calls 'post_disable' drm_bridge_funcs op for |
194 | * drm_bridge_post_disable - calls ->post_disable() &drm_bridge_funcs op for |
212 | * all bridges in the encoder chain. |
195 | * all bridges in the encoder chain. |
213 | * @bridge: bridge control structure |
196 | * @bridge: bridge control structure |
214 | * |
197 | * |
215 | * Calls 'post_disable' drm_bridge_funcs op for all the bridges in the |
198 | * Calls ->post_disable() &drm_bridge_funcs op for all the bridges in the |
216 | * encoder chain, starting from the first bridge to the last. These are called |
199 | * encoder chain, starting from the first bridge to the last. These are called |
217 | * after completing the encoder's prepare op. |
200 | * after completing the encoder's prepare op. |
218 | * |
201 | * |
219 | * Note: the bridge passed should be the one closest to the encoder |
202 | * Note: the bridge passed should be the one closest to the encoder |
220 | */ |
203 | */ |
221 | void drm_bridge_post_disable(struct drm_bridge *bridge) |
204 | void drm_bridge_post_disable(struct drm_bridge *bridge) |
222 | { |
205 | { |
223 | if (!bridge) |
206 | if (!bridge) |
224 | return; |
207 | return; |
225 | 208 | ||
226 | bridge->funcs->post_disable(bridge); |
209 | bridge->funcs->post_disable(bridge); |
227 | 210 | ||
228 | drm_bridge_post_disable(bridge->next); |
211 | drm_bridge_post_disable(bridge->next); |
229 | } |
212 | } |
230 | EXPORT_SYMBOL(drm_bridge_post_disable); |
213 | EXPORT_SYMBOL(drm_bridge_post_disable); |
231 | 214 | ||
232 | /** |
215 | /** |
233 | * drm_bridge_mode_set - set proposed mode for all bridges in the |
216 | * drm_bridge_mode_set - set proposed mode for all bridges in the |
234 | * encoder chain |
217 | * encoder chain |
235 | * @bridge: bridge control structure |
218 | * @bridge: bridge control structure |
236 | * @mode: desired mode to be set for the bridge |
219 | * @mode: desired mode to be set for the bridge |
237 | * @adjusted_mode: updated mode that works for this bridge |
220 | * @adjusted_mode: updated mode that works for this bridge |
238 | * |
221 | * |
239 | * Calls 'mode_set' drm_bridge_funcs op for all the bridges in the |
222 | * Calls ->mode_set() &drm_bridge_funcs op for all the bridges in the |
240 | * encoder chain, starting from the first bridge to the last. |
223 | * encoder chain, starting from the first bridge to the last. |
241 | * |
224 | * |
242 | * Note: the bridge passed should be the one closest to the encoder |
225 | * Note: the bridge passed should be the one closest to the encoder |
243 | */ |
226 | */ |
244 | void drm_bridge_mode_set(struct drm_bridge *bridge, |
227 | void drm_bridge_mode_set(struct drm_bridge *bridge, |
245 | struct drm_display_mode *mode, |
228 | struct drm_display_mode *mode, |
246 | struct drm_display_mode *adjusted_mode) |
229 | struct drm_display_mode *adjusted_mode) |
247 | { |
230 | { |
248 | if (!bridge) |
231 | if (!bridge) |
249 | return; |
232 | return; |
250 | 233 | ||
251 | if (bridge->funcs->mode_set) |
234 | if (bridge->funcs->mode_set) |
252 | bridge->funcs->mode_set(bridge, mode, adjusted_mode); |
235 | bridge->funcs->mode_set(bridge, mode, adjusted_mode); |
253 | 236 | ||
254 | drm_bridge_mode_set(bridge->next, mode, adjusted_mode); |
237 | drm_bridge_mode_set(bridge->next, mode, adjusted_mode); |
255 | } |
238 | } |
256 | EXPORT_SYMBOL(drm_bridge_mode_set); |
239 | EXPORT_SYMBOL(drm_bridge_mode_set); |
257 | 240 | ||
258 | /** |
241 | /** |
259 | * drm_bridge_pre_enable - calls 'pre_enable' drm_bridge_funcs op for all |
242 | * drm_bridge_pre_enable - calls ->pre_enable() &drm_bridge_funcs op for all |
260 | * bridges in the encoder chain. |
243 | * bridges in the encoder chain. |
261 | * @bridge: bridge control structure |
244 | * @bridge: bridge control structure |
262 | * |
245 | * |
263 | * Calls 'pre_enable' drm_bridge_funcs op for all the bridges in the encoder |
246 | * Calls ->pre_enable() &drm_bridge_funcs op for all the bridges in the encoder |
264 | * chain, starting from the last bridge to the first. These are called |
247 | * chain, starting from the last bridge to the first. These are called |
265 | * before calling the encoder's commit op. |
248 | * before calling the encoder's commit op. |
266 | * |
249 | * |
267 | * Note: the bridge passed should be the one closest to the encoder |
250 | * Note: the bridge passed should be the one closest to the encoder |
268 | */ |
251 | */ |
269 | void drm_bridge_pre_enable(struct drm_bridge *bridge) |
252 | void drm_bridge_pre_enable(struct drm_bridge *bridge) |
270 | { |
253 | { |
271 | if (!bridge) |
254 | if (!bridge) |
272 | return; |
255 | return; |
273 | 256 | ||
274 | drm_bridge_pre_enable(bridge->next); |
257 | drm_bridge_pre_enable(bridge->next); |
275 | 258 | ||
276 | bridge->funcs->pre_enable(bridge); |
259 | bridge->funcs->pre_enable(bridge); |
277 | } |
260 | } |
278 | EXPORT_SYMBOL(drm_bridge_pre_enable); |
261 | EXPORT_SYMBOL(drm_bridge_pre_enable); |
279 | 262 | ||
280 | /** |
263 | /** |
281 | * drm_bridge_enable - calls 'enable' drm_bridge_funcs op for all bridges |
264 | * drm_bridge_enable - calls ->enable() &drm_bridge_funcs op for all bridges |
282 | * in the encoder chain. |
265 | * in the encoder chain. |
283 | * @bridge: bridge control structure |
266 | * @bridge: bridge control structure |
284 | * |
267 | * |
285 | * Calls 'enable' drm_bridge_funcs op for all the bridges in the encoder |
268 | * Calls ->enable() &drm_bridge_funcs op for all the bridges in the encoder |
286 | * chain, starting from the first bridge to the last. These are called |
269 | * chain, starting from the first bridge to the last. These are called |
287 | * after completing the encoder's commit op. |
270 | * after completing the encoder's commit op. |
288 | * |
271 | * |
289 | * Note that the bridge passed should be the one closest to the encoder |
272 | * Note that the bridge passed should be the one closest to the encoder |
290 | */ |
273 | */ |
291 | void drm_bridge_enable(struct drm_bridge *bridge) |
274 | void drm_bridge_enable(struct drm_bridge *bridge) |
292 | { |
275 | { |
293 | if (!bridge) |
276 | if (!bridge) |
294 | return; |
277 | return; |
295 | 278 | ||
296 | bridge->funcs->enable(bridge); |
279 | bridge->funcs->enable(bridge); |
297 | 280 | ||
298 | drm_bridge_enable(bridge->next); |
281 | drm_bridge_enable(bridge->next); |
299 | } |
282 | } |
300 | EXPORT_SYMBOL(drm_bridge_enable); |
283 | EXPORT_SYMBOL(drm_bridge_enable); |
301 | 284 | ||
302 | #ifdef CONFIG_OF |
285 | #ifdef CONFIG_OF |
303 | /** |
286 | /** |
304 | * of_drm_find_bridge - find the bridge corresponding to the device node in |
287 | * of_drm_find_bridge - find the bridge corresponding to the device node in |
305 | * the global bridge list |
288 | * the global bridge list |
306 | * |
289 | * |
307 | * @np: device node |
290 | * @np: device node |
308 | * |
291 | * |
309 | * RETURNS: |
292 | * RETURNS: |
310 | * drm_bridge control struct on success, NULL on failure |
293 | * drm_bridge control struct on success, NULL on failure |
311 | */ |
294 | */ |
312 | struct drm_bridge *of_drm_find_bridge(struct device_node *np) |
295 | struct drm_bridge *of_drm_find_bridge(struct device_node *np) |
313 | { |
296 | { |
314 | struct drm_bridge *bridge; |
297 | struct drm_bridge *bridge; |
315 | 298 | ||
316 | mutex_lock(&bridge_lock); |
299 | mutex_lock(&bridge_lock); |
317 | 300 | ||
318 | list_for_each_entry(bridge, &bridge_list, list) { |
301 | list_for_each_entry(bridge, &bridge_list, list) { |
319 | if (bridge->of_node == np) { |
302 | if (bridge->of_node == np) { |
320 | mutex_unlock(&bridge_lock); |
303 | mutex_unlock(&bridge_lock); |
321 | return bridge; |
304 | return bridge; |
322 | } |
305 | } |
323 | } |
306 | } |
324 | 307 | ||
325 | mutex_unlock(&bridge_lock); |
308 | mutex_unlock(&bridge_lock); |
326 | return NULL; |
309 | return NULL; |
327 | } |
310 | } |
328 | EXPORT_SYMBOL(of_drm_find_bridge); |
311 | EXPORT_SYMBOL(of_drm_find_bridge); |
329 | #endif |
312 | #endif |
330 | 313 | ||
331 | MODULE_AUTHOR("Ajay Kumar |
314 | MODULE_AUTHOR("Ajay Kumar |
332 | MODULE_DESCRIPTION("DRM bridge infrastructure"); |
315 | MODULE_DESCRIPTION("DRM bridge infrastructure"); |
333 | MODULE_LICENSE("GPL and additional rights"); |
316 | MODULE_LICENSE("GPL and additional rights"); |