diff options
Diffstat (limited to 'drivers/gpu/drm/drm_bridge.c')
-rw-r--r-- | drivers/gpu/drm/drm_bridge.c | 242 |
1 files changed, 242 insertions, 0 deletions
diff --git a/drivers/gpu/drm/drm_bridge.c b/drivers/gpu/drm/drm_bridge.c index eaa5790c2a6f..6b8f7211e543 100644 --- a/drivers/gpu/drm/drm_bridge.c +++ b/drivers/gpu/drm/drm_bridge.c | |||
@@ -28,9 +28,42 @@ | |||
28 | 28 | ||
29 | #include "drm/drmP.h" | 29 | #include "drm/drmP.h" |
30 | 30 | ||
31 | /** | ||
32 | * DOC: overview | ||
33 | * | ||
34 | * drm_bridge represents a device that hangs on to an encoder. These are handy | ||
35 | * when a regular drm_encoder entity isn't enough to represent the entire | ||
36 | * encoder chain. | ||
37 | * | ||
38 | * A bridge is always associated to a single drm_encoder at a time, but can be | ||
39 | * either connected to it directly, or through an intermediate bridge: | ||
40 | * | ||
41 | * encoder ---> bridge B ---> bridge A | ||
42 | * | ||
43 | * Here, the output of the encoder feeds to bridge B, and that furthers feeds to | ||
44 | * bridge A. | ||
45 | * | ||
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 | ||
48 | * participate along with encoder functions to perform mode_set/enable/disable | ||
49 | * through the ops provided in drm_bridge_funcs. | ||
50 | * | ||
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 | ||
53 | * desired output at the end of the encoder chain. | ||
54 | */ | ||
55 | |||
31 | static DEFINE_MUTEX(bridge_lock); | 56 | static DEFINE_MUTEX(bridge_lock); |
32 | static LIST_HEAD(bridge_list); | 57 | static LIST_HEAD(bridge_list); |
33 | 58 | ||
59 | /** | ||
60 | * drm_bridge_add - add the given bridge to the global bridge list | ||
61 | * | ||
62 | * @bridge: bridge control structure | ||
63 | * | ||
64 | * RETURNS: | ||
65 | * Unconditionally returns Zero. | ||
66 | */ | ||
34 | int drm_bridge_add(struct drm_bridge *bridge) | 67 | int drm_bridge_add(struct drm_bridge *bridge) |
35 | { | 68 | { |
36 | mutex_lock(&bridge_lock); | 69 | mutex_lock(&bridge_lock); |
@@ -41,6 +74,11 @@ int drm_bridge_add(struct drm_bridge *bridge) | |||
41 | } | 74 | } |
42 | EXPORT_SYMBOL(drm_bridge_add); | 75 | EXPORT_SYMBOL(drm_bridge_add); |
43 | 76 | ||
77 | /** | ||
78 | * drm_bridge_remove - remove the given bridge from the global bridge list | ||
79 | * | ||
80 | * @bridge: bridge control structure | ||
81 | */ | ||
44 | void drm_bridge_remove(struct drm_bridge *bridge) | 82 | void drm_bridge_remove(struct drm_bridge *bridge) |
45 | { | 83 | { |
46 | mutex_lock(&bridge_lock); | 84 | mutex_lock(&bridge_lock); |
@@ -49,6 +87,21 @@ void drm_bridge_remove(struct drm_bridge *bridge) | |||
49 | } | 87 | } |
50 | EXPORT_SYMBOL(drm_bridge_remove); | 88 | EXPORT_SYMBOL(drm_bridge_remove); |
51 | 89 | ||
90 | /** | ||
91 | * drm_bridge_attach - associate given bridge to our DRM device | ||
92 | * | ||
93 | * @dev: DRM device | ||
94 | * @bridge: bridge control structure | ||
95 | * | ||
96 | * called by a kms driver to link one of our encoder/bridge to the given | ||
97 | * bridge. | ||
98 | * | ||
99 | * Note that setting up links between the bridge and our encoder/bridge | ||
100 | * objects needs to be handled by the kms driver itself | ||
101 | * | ||
102 | * RETURNS: | ||
103 | * Zero on success, error code on failure | ||
104 | */ | ||
52 | int drm_bridge_attach(struct drm_device *dev, struct drm_bridge *bridge) | 105 | int drm_bridge_attach(struct drm_device *dev, struct drm_bridge *bridge) |
53 | { | 106 | { |
54 | if (!dev || !bridge) | 107 | if (!dev || !bridge) |
@@ -66,7 +119,196 @@ int drm_bridge_attach(struct drm_device *dev, struct drm_bridge *bridge) | |||
66 | } | 119 | } |
67 | EXPORT_SYMBOL(drm_bridge_attach); | 120 | EXPORT_SYMBOL(drm_bridge_attach); |
68 | 121 | ||
122 | /** | ||
123 | * DOC: bridge callbacks | ||
124 | * | ||
125 | * 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 | ||
127 | * These helpers call a specific drm_bridge_funcs op for all the bridges | ||
128 | * during encoder configuration. | ||
129 | * | ||
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 | ||
152 | * (an encoder or a bridge) has set the mode too. | ||
153 | */ | ||
154 | |||
155 | /** | ||
156 | * drm_bridge_mode_fixup - fixup proposed mode for all bridges in the | ||
157 | * encoder chain | ||
158 | * @bridge: bridge control structure | ||
159 | * @mode: desired mode to be set for the bridge | ||
160 | * @adjusted_mode: updated mode that works for this bridge | ||
161 | * | ||
162 | * Calls 'mode_fixup' drm_bridge_funcs op for all the bridges in the | ||
163 | * encoder chain, starting from the first bridge to the last. | ||
164 | * | ||
165 | * Note: the bridge passed should be the one closest to the encoder | ||
166 | * | ||
167 | * RETURNS: | ||
168 | * true on success, false on failure | ||
169 | */ | ||
170 | bool drm_bridge_mode_fixup(struct drm_bridge *bridge, | ||
171 | const struct drm_display_mode *mode, | ||
172 | struct drm_display_mode *adjusted_mode) | ||
173 | { | ||
174 | bool ret = true; | ||
175 | |||
176 | if (!bridge) | ||
177 | return true; | ||
178 | |||
179 | if (bridge->funcs->mode_fixup) | ||
180 | ret = bridge->funcs->mode_fixup(bridge, mode, adjusted_mode); | ||
181 | |||
182 | ret = ret && drm_bridge_mode_fixup(bridge->next, mode, adjusted_mode); | ||
183 | |||
184 | return ret; | ||
185 | } | ||
186 | EXPORT_SYMBOL(drm_bridge_mode_fixup); | ||
187 | |||
188 | /** | ||
189 | * drm_bridge_disable - calls 'disable' drm_bridge_funcs op for all | ||
190 | * bridges in the encoder chain. | ||
191 | * @bridge: bridge control structure | ||
192 | * | ||
193 | * 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 | ||
195 | * calling the encoder's prepare op. | ||
196 | * | ||
197 | * Note: the bridge passed should be the one closest to the encoder | ||
198 | */ | ||
199 | void drm_bridge_disable(struct drm_bridge *bridge) | ||
200 | { | ||
201 | if (!bridge) | ||
202 | return; | ||
203 | |||
204 | drm_bridge_disable(bridge->next); | ||
205 | |||
206 | bridge->funcs->disable(bridge); | ||
207 | } | ||
208 | EXPORT_SYMBOL(drm_bridge_disable); | ||
209 | |||
210 | /** | ||
211 | * drm_bridge_post_disable - calls 'post_disable' drm_bridge_funcs op for | ||
212 | * all bridges in the encoder chain. | ||
213 | * @bridge: bridge control structure | ||
214 | * | ||
215 | * 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 | ||
217 | * after completing the encoder's prepare op. | ||
218 | * | ||
219 | * Note: the bridge passed should be the one closest to the encoder | ||
220 | */ | ||
221 | void drm_bridge_post_disable(struct drm_bridge *bridge) | ||
222 | { | ||
223 | if (!bridge) | ||
224 | return; | ||
225 | |||
226 | bridge->funcs->post_disable(bridge); | ||
227 | |||
228 | drm_bridge_post_disable(bridge->next); | ||
229 | } | ||
230 | EXPORT_SYMBOL(drm_bridge_post_disable); | ||
231 | |||
232 | /** | ||
233 | * drm_bridge_mode_set - set proposed mode for all bridges in the | ||
234 | * encoder chain | ||
235 | * @bridge: bridge control structure | ||
236 | * @mode: desired mode to be set for the bridge | ||
237 | * @adjusted_mode: updated mode that works for this bridge | ||
238 | * | ||
239 | * Calls 'mode_set' drm_bridge_funcs op for all the bridges in the | ||
240 | * encoder chain, starting from the first bridge to the last. | ||
241 | * | ||
242 | * Note: the bridge passed should be the one closest to the encoder | ||
243 | */ | ||
244 | void drm_bridge_mode_set(struct drm_bridge *bridge, | ||
245 | struct drm_display_mode *mode, | ||
246 | struct drm_display_mode *adjusted_mode) | ||
247 | { | ||
248 | if (!bridge) | ||
249 | return; | ||
250 | |||
251 | if (bridge->funcs->mode_set) | ||
252 | bridge->funcs->mode_set(bridge, mode, adjusted_mode); | ||
253 | |||
254 | drm_bridge_mode_set(bridge->next, mode, adjusted_mode); | ||
255 | } | ||
256 | EXPORT_SYMBOL(drm_bridge_mode_set); | ||
257 | |||
258 | /** | ||
259 | * drm_bridge_pre_enable - calls 'pre_enable' drm_bridge_funcs op for all | ||
260 | * bridges in the encoder chain. | ||
261 | * @bridge: bridge control structure | ||
262 | * | ||
263 | * 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 | ||
265 | * before calling the encoder's commit op. | ||
266 | * | ||
267 | * Note: the bridge passed should be the one closest to the encoder | ||
268 | */ | ||
269 | void drm_bridge_pre_enable(struct drm_bridge *bridge) | ||
270 | { | ||
271 | if (!bridge) | ||
272 | return; | ||
273 | |||
274 | drm_bridge_pre_enable(bridge->next); | ||
275 | |||
276 | bridge->funcs->pre_enable(bridge); | ||
277 | } | ||
278 | EXPORT_SYMBOL(drm_bridge_pre_enable); | ||
279 | |||
280 | /** | ||
281 | * drm_bridge_enable - calls 'enable' drm_bridge_funcs op for all bridges | ||
282 | * in the encoder chain. | ||
283 | * @bridge: bridge control structure | ||
284 | * | ||
285 | * 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 | ||
287 | * after completing the encoder's commit op. | ||
288 | * | ||
289 | * Note that the bridge passed should be the one closest to the encoder | ||
290 | */ | ||
291 | void drm_bridge_enable(struct drm_bridge *bridge) | ||
292 | { | ||
293 | if (!bridge) | ||
294 | return; | ||
295 | |||
296 | bridge->funcs->enable(bridge); | ||
297 | |||
298 | drm_bridge_enable(bridge->next); | ||
299 | } | ||
300 | EXPORT_SYMBOL(drm_bridge_enable); | ||
301 | |||
69 | #ifdef CONFIG_OF | 302 | #ifdef CONFIG_OF |
303 | /** | ||
304 | * of_drm_find_bridge - find the bridge corresponding to the device node in | ||
305 | * the global bridge list | ||
306 | * | ||
307 | * @np: device node | ||
308 | * | ||
309 | * RETURNS: | ||
310 | * drm_bridge control struct on success, NULL on failure | ||
311 | */ | ||
70 | struct drm_bridge *of_drm_find_bridge(struct device_node *np) | 312 | struct drm_bridge *of_drm_find_bridge(struct device_node *np) |
71 | { | 313 | { |
72 | struct drm_bridge *bridge; | 314 | struct drm_bridge *bridge; |