Rev 6937 | Only display areas with differences | Regard whitespace | Details | Blame | Last modification | View Log | RSS feed
Rev 6937 | Rev 7144 | ||
---|---|---|---|
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 | * struct &drm_bridge represents a device that hangs on to an encoder. These are |
34 | * struct &drm_bridge represents a device that hangs on to an encoder. These are |
35 | * handy 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 attached 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 and hence are not visible to userspace. They |
52 | * CRTCs, encoders or connectors and hence are not visible to userspace. They |
53 | * just provide additional hooks to get the desired output at the end of the |
53 | * just provide additional hooks to get the desired output at the end of the |
54 | * encoder chain. |
54 | * encoder chain. |
55 | * |
55 | * |
56 | * Bridges can also be chained up using the next pointer in struct &drm_bridge. |
56 | * Bridges can also be chained up using the next pointer in struct &drm_bridge. |
57 | * |
57 | * |
58 | * Both legacy CRTC helpers and the new atomic modeset helpers support bridges. |
58 | * Both legacy CRTC helpers and the new atomic modeset helpers support bridges. |
59 | */ |
59 | */ |
60 | 60 | ||
61 | static DEFINE_MUTEX(bridge_lock); |
61 | static DEFINE_MUTEX(bridge_lock); |
62 | static LIST_HEAD(bridge_list); |
62 | static LIST_HEAD(bridge_list); |
63 | 63 | ||
64 | /** |
64 | /** |
65 | * 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 |
66 | * |
66 | * |
67 | * @bridge: bridge control structure |
67 | * @bridge: bridge control structure |
68 | * |
68 | * |
69 | * RETURNS: |
69 | * RETURNS: |
70 | * Unconditionally returns Zero. |
70 | * Unconditionally returns Zero. |
71 | */ |
71 | */ |
72 | int drm_bridge_add(struct drm_bridge *bridge) |
72 | int drm_bridge_add(struct drm_bridge *bridge) |
73 | { |
73 | { |
74 | mutex_lock(&bridge_lock); |
74 | mutex_lock(&bridge_lock); |
75 | list_add_tail(&bridge->list, &bridge_list); |
75 | list_add_tail(&bridge->list, &bridge_list); |
76 | mutex_unlock(&bridge_lock); |
76 | mutex_unlock(&bridge_lock); |
77 | 77 | ||
78 | return 0; |
78 | return 0; |
79 | } |
79 | } |
80 | EXPORT_SYMBOL(drm_bridge_add); |
80 | EXPORT_SYMBOL(drm_bridge_add); |
81 | 81 | ||
82 | /** |
82 | /** |
83 | * 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 |
84 | * |
84 | * |
85 | * @bridge: bridge control structure |
85 | * @bridge: bridge control structure |
86 | */ |
86 | */ |
87 | void drm_bridge_remove(struct drm_bridge *bridge) |
87 | void drm_bridge_remove(struct drm_bridge *bridge) |
88 | { |
88 | { |
89 | mutex_lock(&bridge_lock); |
89 | mutex_lock(&bridge_lock); |
90 | list_del_init(&bridge->list); |
90 | list_del_init(&bridge->list); |
91 | mutex_unlock(&bridge_lock); |
91 | mutex_unlock(&bridge_lock); |
92 | } |
92 | } |
93 | EXPORT_SYMBOL(drm_bridge_remove); |
93 | EXPORT_SYMBOL(drm_bridge_remove); |
94 | 94 | ||
95 | /** |
95 | /** |
96 | * drm_bridge_attach - associate given bridge to our DRM device |
96 | * drm_bridge_attach - associate given bridge to our DRM device |
97 | * |
97 | * |
98 | * @dev: DRM device |
98 | * @dev: DRM device |
99 | * @bridge: bridge control structure |
99 | * @bridge: bridge control structure |
100 | * |
100 | * |
101 | * 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 |
102 | * bridge. |
102 | * bridge. |
103 | * |
103 | * |
104 | * 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 |
105 | * objects needs to be handled by the kms driver itself |
105 | * objects needs to be handled by the kms driver itself |
106 | * |
106 | * |
107 | * RETURNS: |
107 | * RETURNS: |
108 | * Zero on success, error code on failure |
108 | * Zero on success, error code on failure |
109 | */ |
109 | */ |
110 | 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) |
111 | { |
111 | { |
112 | if (!dev || !bridge) |
112 | if (!dev || !bridge) |
113 | return -EINVAL; |
113 | return -EINVAL; |
114 | 114 | ||
115 | if (bridge->dev) |
115 | if (bridge->dev) |
116 | return -EBUSY; |
116 | return -EBUSY; |
117 | 117 | ||
118 | bridge->dev = dev; |
118 | bridge->dev = dev; |
119 | 119 | ||
120 | if (bridge->funcs->attach) |
120 | if (bridge->funcs->attach) |
121 | return bridge->funcs->attach(bridge); |
121 | return bridge->funcs->attach(bridge); |
122 | 122 | ||
123 | return 0; |
123 | return 0; |
124 | } |
124 | } |
125 | EXPORT_SYMBOL(drm_bridge_attach); |
125 | EXPORT_SYMBOL(drm_bridge_attach); |
126 | 126 | ||
127 | /** |
127 | /** |
128 | * DOC: bridge callbacks |
128 | * DOC: bridge callbacks |
129 | * |
129 | * |
130 | * 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 |
131 | * 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 |
132 | * 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 |
133 | * during encoder configuration. |
133 | * during encoder configuration. |
134 | * |
134 | * |
135 | * For detailed specification of the bridge callbacks see &drm_bridge_funcs. |
135 | * For detailed specification of the bridge callbacks see &drm_bridge_funcs. |
136 | */ |
136 | */ |
137 | 137 | ||
138 | /** |
138 | /** |
139 | * 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 |
140 | * encoder chain |
140 | * encoder chain |
141 | * @bridge: bridge control structure |
141 | * @bridge: bridge control structure |
142 | * @mode: desired mode to be set for the bridge |
142 | * @mode: desired mode to be set for the bridge |
143 | * @adjusted_mode: updated mode that works for this bridge |
143 | * @adjusted_mode: updated mode that works for this bridge |
144 | * |
144 | * |
145 | * 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 |
146 | * encoder chain, starting from the first bridge to the last. |
146 | * encoder chain, starting from the first bridge to the last. |
147 | * |
147 | * |
148 | * 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 |
149 | * |
149 | * |
150 | * RETURNS: |
150 | * RETURNS: |
151 | * true on success, false on failure |
151 | * true on success, false on failure |
152 | */ |
152 | */ |
153 | bool drm_bridge_mode_fixup(struct drm_bridge *bridge, |
153 | bool drm_bridge_mode_fixup(struct drm_bridge *bridge, |
154 | const struct drm_display_mode *mode, |
154 | const struct drm_display_mode *mode, |
155 | struct drm_display_mode *adjusted_mode) |
155 | struct drm_display_mode *adjusted_mode) |
156 | { |
156 | { |
157 | bool ret = true; |
157 | bool ret = true; |
158 | 158 | ||
159 | if (!bridge) |
159 | if (!bridge) |
160 | return true; |
160 | return true; |
161 | 161 | ||
162 | if (bridge->funcs->mode_fixup) |
162 | if (bridge->funcs->mode_fixup) |
163 | ret = bridge->funcs->mode_fixup(bridge, mode, adjusted_mode); |
163 | ret = bridge->funcs->mode_fixup(bridge, mode, adjusted_mode); |
164 | 164 | ||
165 | ret = ret && drm_bridge_mode_fixup(bridge->next, mode, adjusted_mode); |
165 | ret = ret && drm_bridge_mode_fixup(bridge->next, mode, adjusted_mode); |
166 | 166 | ||
167 | return ret; |
167 | return ret; |
168 | } |
168 | } |
169 | EXPORT_SYMBOL(drm_bridge_mode_fixup); |
169 | EXPORT_SYMBOL(drm_bridge_mode_fixup); |
170 | 170 | ||
171 | /** |
171 | /** |
172 | * drm_bridge_disable - calls ->disable() &drm_bridge_funcs op for all |
172 | * drm_bridge_disable - calls ->disable() &drm_bridge_funcs op for all |
173 | * bridges in the encoder chain. |
173 | * bridges in the encoder chain. |
174 | * @bridge: bridge control structure |
174 | * @bridge: bridge control structure |
175 | * |
175 | * |
176 | * 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 |
177 | * 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 |
178 | * calling the encoder's prepare op. |
178 | * calling the encoder's prepare op. |
179 | * |
179 | * |
180 | * 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 |
181 | */ |
181 | */ |
182 | void drm_bridge_disable(struct drm_bridge *bridge) |
182 | void drm_bridge_disable(struct drm_bridge *bridge) |
183 | { |
183 | { |
184 | if (!bridge) |
184 | if (!bridge) |
185 | return; |
185 | return; |
186 | 186 | ||
187 | drm_bridge_disable(bridge->next); |
187 | drm_bridge_disable(bridge->next); |
- | 188 | ||
188 | 189 | if (bridge->funcs->disable) |
|
189 | bridge->funcs->disable(bridge); |
190 | bridge->funcs->disable(bridge); |
190 | } |
191 | } |
191 | EXPORT_SYMBOL(drm_bridge_disable); |
192 | EXPORT_SYMBOL(drm_bridge_disable); |
192 | 193 | ||
193 | /** |
194 | /** |
194 | * drm_bridge_post_disable - calls ->post_disable() &drm_bridge_funcs op for |
195 | * drm_bridge_post_disable - calls ->post_disable() &drm_bridge_funcs op for |
195 | * all bridges in the encoder chain. |
196 | * all bridges in the encoder chain. |
196 | * @bridge: bridge control structure |
197 | * @bridge: bridge control structure |
197 | * |
198 | * |
198 | * Calls ->post_disable() &drm_bridge_funcs op for all the bridges in the |
199 | * Calls ->post_disable() &drm_bridge_funcs op for all the bridges in the |
199 | * encoder chain, starting from the first bridge to the last. These are called |
200 | * encoder chain, starting from the first bridge to the last. These are called |
200 | * after completing the encoder's prepare op. |
201 | * after completing the encoder's prepare op. |
201 | * |
202 | * |
202 | * Note: the bridge passed should be the one closest to the encoder |
203 | * Note: the bridge passed should be the one closest to the encoder |
203 | */ |
204 | */ |
204 | void drm_bridge_post_disable(struct drm_bridge *bridge) |
205 | void drm_bridge_post_disable(struct drm_bridge *bridge) |
205 | { |
206 | { |
206 | if (!bridge) |
207 | if (!bridge) |
207 | return; |
208 | return; |
- | 209 | ||
208 | 210 | if (bridge->funcs->post_disable) |
|
209 | bridge->funcs->post_disable(bridge); |
211 | bridge->funcs->post_disable(bridge); |
210 | 212 | ||
211 | drm_bridge_post_disable(bridge->next); |
213 | drm_bridge_post_disable(bridge->next); |
212 | } |
214 | } |
213 | EXPORT_SYMBOL(drm_bridge_post_disable); |
215 | EXPORT_SYMBOL(drm_bridge_post_disable); |
214 | 216 | ||
215 | /** |
217 | /** |
216 | * drm_bridge_mode_set - set proposed mode for all bridges in the |
218 | * drm_bridge_mode_set - set proposed mode for all bridges in the |
217 | * encoder chain |
219 | * encoder chain |
218 | * @bridge: bridge control structure |
220 | * @bridge: bridge control structure |
219 | * @mode: desired mode to be set for the bridge |
221 | * @mode: desired mode to be set for the bridge |
220 | * @adjusted_mode: updated mode that works for this bridge |
222 | * @adjusted_mode: updated mode that works for this bridge |
221 | * |
223 | * |
222 | * Calls ->mode_set() &drm_bridge_funcs op for all the bridges in the |
224 | * Calls ->mode_set() &drm_bridge_funcs op for all the bridges in the |
223 | * encoder chain, starting from the first bridge to the last. |
225 | * encoder chain, starting from the first bridge to the last. |
224 | * |
226 | * |
225 | * Note: the bridge passed should be the one closest to the encoder |
227 | * Note: the bridge passed should be the one closest to the encoder |
226 | */ |
228 | */ |
227 | void drm_bridge_mode_set(struct drm_bridge *bridge, |
229 | void drm_bridge_mode_set(struct drm_bridge *bridge, |
228 | struct drm_display_mode *mode, |
230 | struct drm_display_mode *mode, |
229 | struct drm_display_mode *adjusted_mode) |
231 | struct drm_display_mode *adjusted_mode) |
230 | { |
232 | { |
231 | if (!bridge) |
233 | if (!bridge) |
232 | return; |
234 | return; |
233 | 235 | ||
234 | if (bridge->funcs->mode_set) |
236 | if (bridge->funcs->mode_set) |
235 | bridge->funcs->mode_set(bridge, mode, adjusted_mode); |
237 | bridge->funcs->mode_set(bridge, mode, adjusted_mode); |
236 | 238 | ||
237 | drm_bridge_mode_set(bridge->next, mode, adjusted_mode); |
239 | drm_bridge_mode_set(bridge->next, mode, adjusted_mode); |
238 | } |
240 | } |
239 | EXPORT_SYMBOL(drm_bridge_mode_set); |
241 | EXPORT_SYMBOL(drm_bridge_mode_set); |
240 | 242 | ||
241 | /** |
243 | /** |
242 | * drm_bridge_pre_enable - calls ->pre_enable() &drm_bridge_funcs op for all |
244 | * drm_bridge_pre_enable - calls ->pre_enable() &drm_bridge_funcs op for all |
243 | * bridges in the encoder chain. |
245 | * bridges in the encoder chain. |
244 | * @bridge: bridge control structure |
246 | * @bridge: bridge control structure |
245 | * |
247 | * |
246 | * Calls ->pre_enable() &drm_bridge_funcs op for all the bridges in the encoder |
248 | * Calls ->pre_enable() &drm_bridge_funcs op for all the bridges in the encoder |
247 | * chain, starting from the last bridge to the first. These are called |
249 | * chain, starting from the last bridge to the first. These are called |
248 | * before calling the encoder's commit op. |
250 | * before calling the encoder's commit op. |
249 | * |
251 | * |
250 | * Note: the bridge passed should be the one closest to the encoder |
252 | * Note: the bridge passed should be the one closest to the encoder |
251 | */ |
253 | */ |
252 | void drm_bridge_pre_enable(struct drm_bridge *bridge) |
254 | void drm_bridge_pre_enable(struct drm_bridge *bridge) |
253 | { |
255 | { |
254 | if (!bridge) |
256 | if (!bridge) |
255 | return; |
257 | return; |
256 | 258 | ||
257 | drm_bridge_pre_enable(bridge->next); |
259 | drm_bridge_pre_enable(bridge->next); |
- | 260 | ||
258 | 261 | if (bridge->funcs->pre_enable) |
|
259 | bridge->funcs->pre_enable(bridge); |
262 | bridge->funcs->pre_enable(bridge); |
260 | } |
263 | } |
261 | EXPORT_SYMBOL(drm_bridge_pre_enable); |
264 | EXPORT_SYMBOL(drm_bridge_pre_enable); |
262 | 265 | ||
263 | /** |
266 | /** |
264 | * drm_bridge_enable - calls ->enable() &drm_bridge_funcs op for all bridges |
267 | * drm_bridge_enable - calls ->enable() &drm_bridge_funcs op for all bridges |
265 | * in the encoder chain. |
268 | * in the encoder chain. |
266 | * @bridge: bridge control structure |
269 | * @bridge: bridge control structure |
267 | * |
270 | * |
268 | * Calls ->enable() &drm_bridge_funcs op for all the bridges in the encoder |
271 | * Calls ->enable() &drm_bridge_funcs op for all the bridges in the encoder |
269 | * chain, starting from the first bridge to the last. These are called |
272 | * chain, starting from the first bridge to the last. These are called |
270 | * after completing the encoder's commit op. |
273 | * after completing the encoder's commit op. |
271 | * |
274 | * |
272 | * Note that the bridge passed should be the one closest to the encoder |
275 | * Note that the bridge passed should be the one closest to the encoder |
273 | */ |
276 | */ |
274 | void drm_bridge_enable(struct drm_bridge *bridge) |
277 | void drm_bridge_enable(struct drm_bridge *bridge) |
275 | { |
278 | { |
276 | if (!bridge) |
279 | if (!bridge) |
277 | return; |
280 | return; |
- | 281 | ||
278 | 282 | if (bridge->funcs->enable) |
|
279 | bridge->funcs->enable(bridge); |
283 | bridge->funcs->enable(bridge); |
280 | 284 | ||
281 | drm_bridge_enable(bridge->next); |
285 | drm_bridge_enable(bridge->next); |
282 | } |
286 | } |
283 | EXPORT_SYMBOL(drm_bridge_enable); |
287 | EXPORT_SYMBOL(drm_bridge_enable); |
284 | 288 | ||
285 | #ifdef CONFIG_OF |
289 | #ifdef CONFIG_OF |
286 | /** |
290 | /** |
287 | * of_drm_find_bridge - find the bridge corresponding to the device node in |
291 | * of_drm_find_bridge - find the bridge corresponding to the device node in |
288 | * the global bridge list |
292 | * the global bridge list |
289 | * |
293 | * |
290 | * @np: device node |
294 | * @np: device node |
291 | * |
295 | * |
292 | * RETURNS: |
296 | * RETURNS: |
293 | * drm_bridge control struct on success, NULL on failure |
297 | * drm_bridge control struct on success, NULL on failure |
294 | */ |
298 | */ |
295 | struct drm_bridge *of_drm_find_bridge(struct device_node *np) |
299 | struct drm_bridge *of_drm_find_bridge(struct device_node *np) |
296 | { |
300 | { |
297 | struct drm_bridge *bridge; |
301 | struct drm_bridge *bridge; |
298 | 302 | ||
299 | mutex_lock(&bridge_lock); |
303 | mutex_lock(&bridge_lock); |
300 | 304 | ||
301 | list_for_each_entry(bridge, &bridge_list, list) { |
305 | list_for_each_entry(bridge, &bridge_list, list) { |
302 | if (bridge->of_node == np) { |
306 | if (bridge->of_node == np) { |
303 | mutex_unlock(&bridge_lock); |
307 | mutex_unlock(&bridge_lock); |
304 | return bridge; |
308 | return bridge; |
305 | } |
309 | } |
306 | } |
310 | } |
307 | 311 | ||
308 | mutex_unlock(&bridge_lock); |
312 | mutex_unlock(&bridge_lock); |
309 | return NULL; |
313 | return NULL; |
310 | } |
314 | } |
311 | EXPORT_SYMBOL(of_drm_find_bridge); |
315 | EXPORT_SYMBOL(of_drm_find_bridge); |
312 | #endif |
316 | #endif |
313 | 317 | ||
314 | MODULE_AUTHOR("Ajay Kumar |
318 | MODULE_AUTHOR("Ajay Kumar |
315 | MODULE_DESCRIPTION("DRM bridge infrastructure"); |
319 | MODULE_DESCRIPTION("DRM bridge infrastructure"); |
316 | MODULE_LICENSE("GPL and additional rights"); |
320 | MODULE_LICENSE("GPL and additional rights"); |