Skip to content

Commit 5ade071

Browse files
committed
drm: Add atomic variants for bridge enable/disable
This patch adds atomic variants for all of pre_enable/enable/disable/post_disable bridge functions. These will be called from the appropriate atomic helper functions. If the bridge driver doesn't implement the atomic version of the function, we will fall back to the vanilla implementation. Note that some drivers call drm_bridge_disable directly, and these cases are not covered. It's up to the driver to decide whether to implement both atomic_disable and disable, or if it's not necessary. Changes in v3: - Added to the patchset Changes in v4: - Fix up docbook references (Daniel) Changes in v5: - None Link to v3: https://patchwork.freedesktop.org/patch/msgid/[email protected] Link to v4: https://patchwork.freedesktop.org/patch/msgid/[email protected] Cc: Daniel Vetter <[email protected]> Cc: Ville Syrjälä <[email protected]> Tested-by: Heiko Stuebner <[email protected]> Reviewed-by: Daniel Vetter <[email protected]> Reviewed-by: Andrzej Hajda <[email protected]> Signed-off-by: Sean Paul <[email protected]> Link: https://patchwork.freedesktop.org/patch/msgid/[email protected]
1 parent 1b27fbd commit 5ade071

File tree

3 files changed

+220
-4
lines changed

3 files changed

+220
-4
lines changed

drivers/gpu/drm/drm_atomic_helper.c

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -998,7 +998,7 @@ disable_outputs(struct drm_device *dev, struct drm_atomic_state *old_state)
998998
* Each encoder has at most one connector (since we always steal
999999
* it away), so we won't call disable hooks twice.
10001000
*/
1001-
drm_bridge_disable(encoder->bridge);
1001+
drm_atomic_bridge_disable(encoder->bridge, old_state);
10021002

10031003
/* Right function depends upon target state. */
10041004
if (funcs) {
@@ -1012,7 +1012,7 @@ disable_outputs(struct drm_device *dev, struct drm_atomic_state *old_state)
10121012
funcs->dpms(encoder, DRM_MODE_DPMS_OFF);
10131013
}
10141014

1015-
drm_bridge_post_disable(encoder->bridge);
1015+
drm_atomic_bridge_post_disable(encoder->bridge, old_state);
10161016
}
10171017

10181018
for_each_oldnew_crtc_in_state(old_state, crtc, old_crtc_state, new_crtc_state, i) {
@@ -1310,7 +1310,7 @@ void drm_atomic_helper_commit_modeset_enables(struct drm_device *dev,
13101310
* Each encoder has at most one connector (since we always steal
13111311
* it away), so we won't call enable hooks twice.
13121312
*/
1313-
drm_bridge_pre_enable(encoder->bridge);
1313+
drm_atomic_bridge_pre_enable(encoder->bridge, old_state);
13141314

13151315
if (funcs) {
13161316
if (funcs->atomic_enable)
@@ -1321,7 +1321,7 @@ void drm_atomic_helper_commit_modeset_enables(struct drm_device *dev,
13211321
funcs->commit(encoder);
13221322
}
13231323

1324-
drm_bridge_enable(encoder->bridge);
1324+
drm_atomic_bridge_enable(encoder->bridge, old_state);
13251325
}
13261326

13271327
drm_atomic_helper_commit_writebacks(dev, old_state);

drivers/gpu/drm/drm_bridge.c

Lines changed: 110 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -352,6 +352,116 @@ void drm_bridge_enable(struct drm_bridge *bridge)
352352
}
353353
EXPORT_SYMBOL(drm_bridge_enable);
354354

355+
/**
356+
* drm_atomic_bridge_disable - disables all bridges in the encoder chain
357+
* @bridge: bridge control structure
358+
* @state: atomic state being committed
359+
*
360+
* Calls &drm_bridge_funcs.atomic_disable (falls back on
361+
* &drm_bridge_funcs.disable) op for all the bridges in the encoder chain,
362+
* starting from the last bridge to the first. These are called before calling
363+
* &drm_encoder_helper_funcs.atomic_disable
364+
*
365+
* Note: the bridge passed should be the one closest to the encoder
366+
*/
367+
void drm_atomic_bridge_disable(struct drm_bridge *bridge,
368+
struct drm_atomic_state *state)
369+
{
370+
if (!bridge)
371+
return;
372+
373+
drm_atomic_bridge_disable(bridge->next, state);
374+
375+
if (bridge->funcs->atomic_disable)
376+
bridge->funcs->atomic_disable(bridge, state);
377+
else if (bridge->funcs->disable)
378+
bridge->funcs->disable(bridge);
379+
}
380+
EXPORT_SYMBOL(drm_atomic_bridge_disable);
381+
382+
/**
383+
* drm_atomic_bridge_post_disable - cleans up after disabling all bridges in the
384+
* encoder chain
385+
* @bridge: bridge control structure
386+
* @state: atomic state being committed
387+
*
388+
* Calls &drm_bridge_funcs.atomic_post_disable (falls back on
389+
* &drm_bridge_funcs.post_disable) op for all the bridges in the encoder chain,
390+
* starting from the first bridge to the last. These are called after completing
391+
* &drm_encoder_helper_funcs.atomic_disable
392+
*
393+
* Note: the bridge passed should be the one closest to the encoder
394+
*/
395+
void drm_atomic_bridge_post_disable(struct drm_bridge *bridge,
396+
struct drm_atomic_state *state)
397+
{
398+
if (!bridge)
399+
return;
400+
401+
if (bridge->funcs->atomic_post_disable)
402+
bridge->funcs->atomic_post_disable(bridge, state);
403+
else if (bridge->funcs->post_disable)
404+
bridge->funcs->post_disable(bridge);
405+
406+
drm_atomic_bridge_post_disable(bridge->next, state);
407+
}
408+
EXPORT_SYMBOL(drm_atomic_bridge_post_disable);
409+
410+
/**
411+
* drm_atomic_bridge_pre_enable - prepares for enabling all bridges in the
412+
* encoder chain
413+
* @bridge: bridge control structure
414+
* @state: atomic state being committed
415+
*
416+
* Calls &drm_bridge_funcs.atomic_pre_enable (falls back on
417+
* &drm_bridge_funcs.pre_enable) op for all the bridges in the encoder chain,
418+
* starting from the last bridge to the first. These are called before calling
419+
* &drm_encoder_helper_funcs.atomic_enable
420+
*
421+
* Note: the bridge passed should be the one closest to the encoder
422+
*/
423+
void drm_atomic_bridge_pre_enable(struct drm_bridge *bridge,
424+
struct drm_atomic_state *state)
425+
{
426+
if (!bridge)
427+
return;
428+
429+
drm_atomic_bridge_pre_enable(bridge->next, state);
430+
431+
if (bridge->funcs->atomic_pre_enable)
432+
bridge->funcs->atomic_pre_enable(bridge, state);
433+
else if (bridge->funcs->pre_enable)
434+
bridge->funcs->pre_enable(bridge);
435+
}
436+
EXPORT_SYMBOL(drm_atomic_bridge_pre_enable);
437+
438+
/**
439+
* drm_atomic_bridge_enable - enables all bridges in the encoder chain
440+
* @bridge: bridge control structure
441+
* @state: atomic state being committed
442+
*
443+
* Calls &drm_bridge_funcs.atomic_enable (falls back on
444+
* &drm_bridge_funcs.enable) op for all the bridges in the encoder chain,
445+
* starting from the first bridge to the last. These are called after completing
446+
* &drm_encoder_helper_funcs.atomic_enable
447+
*
448+
* Note: the bridge passed should be the one closest to the encoder
449+
*/
450+
void drm_atomic_bridge_enable(struct drm_bridge *bridge,
451+
struct drm_atomic_state *state)
452+
{
453+
if (!bridge)
454+
return;
455+
456+
if (bridge->funcs->atomic_enable)
457+
bridge->funcs->atomic_enable(bridge, state);
458+
else if (bridge->funcs->enable)
459+
bridge->funcs->enable(bridge);
460+
461+
drm_atomic_bridge_enable(bridge->next, state);
462+
}
463+
EXPORT_SYMBOL(drm_atomic_bridge_enable);
464+
355465
#ifdef CONFIG_OF
356466
/**
357467
* of_drm_find_bridge - find the bridge corresponding to the device node in

include/drm/drm_bridge.h

Lines changed: 106 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -237,6 +237,103 @@ struct drm_bridge_funcs {
237237
* The enable callback is optional.
238238
*/
239239
void (*enable)(struct drm_bridge *bridge);
240+
241+
/**
242+
* @atomic_pre_enable:
243+
*
244+
* This callback should enable the bridge. It is called right before
245+
* the preceding element in the display pipe is enabled. If the
246+
* preceding element is a bridge this means it's called before that
247+
* bridge's @atomic_pre_enable or @pre_enable function. If the preceding
248+
* element is a &drm_encoder it's called right before the encoder's
249+
* &drm_encoder_helper_funcs.atomic_enable hook.
250+
*
251+
* The display pipe (i.e. clocks and timing signals) feeding this bridge
252+
* will not yet be running when this callback is called. The bridge must
253+
* not enable the display link feeding the next bridge in the chain (if
254+
* there is one) when this callback is called.
255+
*
256+
* Note that this function will only be invoked in the context of an
257+
* atomic commit. It will not be invoked from &drm_bridge_pre_enable. It
258+
* would be prudent to also provide an implementation of @pre_enable if
259+
* you are expecting driver calls into &drm_bridge_pre_enable.
260+
*
261+
* The @atomic_pre_enable callback is optional.
262+
*/
263+
void (*atomic_pre_enable)(struct drm_bridge *bridge,
264+
struct drm_atomic_state *state);
265+
266+
/**
267+
* @atomic_enable:
268+
*
269+
* This callback should enable the bridge. It is called right after
270+
* the preceding element in the display pipe is enabled. If the
271+
* preceding element is a bridge this means it's called after that
272+
* bridge's @atomic_enable or @enable function. If the preceding element
273+
* is a &drm_encoder it's called right after the encoder's
274+
* &drm_encoder_helper_funcs.atomic_enable hook.
275+
*
276+
* The bridge can assume that the display pipe (i.e. clocks and timing
277+
* signals) feeding it is running when this callback is called. This
278+
* callback must enable the display link feeding the next bridge in the
279+
* chain if there is one.
280+
*
281+
* Note that this function will only be invoked in the context of an
282+
* atomic commit. It will not be invoked from &drm_bridge_enable. It
283+
* would be prudent to also provide an implementation of @enable if
284+
* you are expecting driver calls into &drm_bridge_enable.
285+
*
286+
* The enable callback is optional.
287+
*/
288+
void (*atomic_enable)(struct drm_bridge *bridge,
289+
struct drm_atomic_state *state);
290+
/**
291+
* @atomic_disable:
292+
*
293+
* This callback should disable the bridge. It is called right before
294+
* the preceding element in the display pipe is disabled. If the
295+
* preceding element is a bridge this means it's called before that
296+
* bridge's @atomic_disable or @disable vfunc. If the preceding element
297+
* is a &drm_encoder it's called right before the
298+
* &drm_encoder_helper_funcs.atomic_disable hook.
299+
*
300+
* The bridge can assume that the display pipe (i.e. clocks and timing
301+
* signals) feeding it is still running when this callback is called.
302+
*
303+
* Note that this function will only be invoked in the context of an
304+
* atomic commit. It will not be invoked from &drm_bridge_disable. It
305+
* would be prudent to also provide an implementation of @disable if
306+
* you are expecting driver calls into &drm_bridge_disable.
307+
*
308+
* The disable callback is optional.
309+
*/
310+
void (*atomic_disable)(struct drm_bridge *bridge,
311+
struct drm_atomic_state *state);
312+
313+
/**
314+
* @atomic_post_disable:
315+
*
316+
* This callback should disable the bridge. It is called right after the
317+
* preceding element in the display pipe is disabled. If the preceding
318+
* element is a bridge this means it's called after that bridge's
319+
* @atomic_post_disable or @post_disable function. If the preceding
320+
* element is a &drm_encoder it's called right after the encoder's
321+
* &drm_encoder_helper_funcs.atomic_disable hook.
322+
*
323+
* The bridge must assume that the display pipe (i.e. clocks and timing
324+
* signals) feeding it is no longer running when this callback is
325+
* called.
326+
*
327+
* Note that this function will only be invoked in the context of an
328+
* atomic commit. It will not be invoked from &drm_bridge_post_disable.
329+
* It would be prudent to also provide an implementation of
330+
* @post_disable if you are expecting driver calls into
331+
* &drm_bridge_post_disable.
332+
*
333+
* The post_disable callback is optional.
334+
*/
335+
void (*atomic_post_disable)(struct drm_bridge *bridge,
336+
struct drm_atomic_state *state);
240337
};
241338

242339
/**
@@ -314,6 +411,15 @@ void drm_bridge_mode_set(struct drm_bridge *bridge,
314411
void drm_bridge_pre_enable(struct drm_bridge *bridge);
315412
void drm_bridge_enable(struct drm_bridge *bridge);
316413

414+
void drm_atomic_bridge_disable(struct drm_bridge *bridge,
415+
struct drm_atomic_state *state);
416+
void drm_atomic_bridge_post_disable(struct drm_bridge *bridge,
417+
struct drm_atomic_state *state);
418+
void drm_atomic_bridge_pre_enable(struct drm_bridge *bridge,
419+
struct drm_atomic_state *state);
420+
void drm_atomic_bridge_enable(struct drm_bridge *bridge,
421+
struct drm_atomic_state *state);
422+
317423
#ifdef CONFIG_DRM_PANEL_BRIDGE
318424
struct drm_bridge *drm_panel_bridge_add(struct drm_panel *panel,
319425
u32 connector_type);

0 commit comments

Comments
 (0)