if (!funcs)
                        continue;
 
-               if (encoder->bridge && encoder->bridge->funcs->mode_fixup) {
-                       ret = encoder->bridge->funcs->mode_fixup(
-                                       encoder->bridge, &crtc_state->mode,
-                                       &crtc_state->adjusted_mode);
-                       if (!ret) {
-                               DRM_DEBUG_ATOMIC("Bridge fixup failed\n");
-                               return -EINVAL;
-                       }
+               ret = drm_bridge_mode_fixup(encoder->bridge, &crtc_state->mode,
+                               &crtc_state->adjusted_mode);
+               if (!ret) {
+                       DRM_DEBUG_ATOMIC("Bridge fixup failed\n");
+                       return -EINVAL;
                }
 
                if (funcs->atomic_check) {
                 * Each encoder has at most one connector (since we always steal
                 * it away), so we won't call disable hooks twice.
                 */
-               if (encoder->bridge)
-                       encoder->bridge->funcs->disable(encoder->bridge);
+               drm_bridge_disable(encoder->bridge);
 
                /* Right function depends upon target state. */
                if (connector->state->crtc && funcs->prepare)
                else
                        funcs->dpms(encoder, DRM_MODE_DPMS_OFF);
 
-               if (encoder->bridge)
-                       encoder->bridge->funcs->post_disable(encoder->bridge);
+               drm_bridge_post_disable(encoder->bridge);
        }
 
        for_each_crtc_in_state(old_state, crtc, old_crtc_state, i) {
                if (funcs->mode_set)
                        funcs->mode_set(encoder, mode, adjusted_mode);
 
-               if (encoder->bridge && encoder->bridge->funcs->mode_set)
-                       encoder->bridge->funcs->mode_set(encoder->bridge,
-                                                        mode, adjusted_mode);
+               drm_bridge_mode_set(encoder->bridge, mode, adjusted_mode);
        }
 }
 
                 * Each encoder has at most one connector (since we always steal
                 * it away), so we won't call enable hooks twice.
                 */
-               if (encoder->bridge)
-                       encoder->bridge->funcs->pre_enable(encoder->bridge);
+               drm_bridge_pre_enable(encoder->bridge);
 
                if (funcs->enable)
                        funcs->enable(encoder);
                else
                        funcs->commit(encoder);
 
-               if (encoder->bridge)
-                       encoder->bridge->funcs->enable(encoder->bridge);
+               drm_bridge_enable(encoder->bridge);
        }
 }
 EXPORT_SYMBOL(drm_atomic_helper_commit_modeset_enables);
 
 }
 EXPORT_SYMBOL(drm_bridge_attach);
 
+/**
+ * drm_bridge_mode_fixup - fixup proposed mode for all bridges in the
+ *                        encoder chain
+ * @bridge: bridge control structure
+ * @mode: desired mode to be set for the bridge
+ * @adjusted_mode: updated mode that works for this bridge
+ *
+ * Calls 'mode_fixup' drm_bridge_funcs op for all the bridges in the
+ * encoder chain, starting from the first bridge to the last.
+ *
+ * Note: the bridge passed should be the one closest to the encoder
+ *
+ * RETURNS:
+ * true on success, false on failure
+ */
+bool drm_bridge_mode_fixup(struct drm_bridge *bridge,
+                       const struct drm_display_mode *mode,
+                       struct drm_display_mode *adjusted_mode)
+{
+       bool ret = true;
+
+       if (!bridge)
+               return true;
+
+       if (bridge->funcs->mode_fixup)
+               ret = bridge->funcs->mode_fixup(bridge, mode, adjusted_mode);
+
+       ret = ret && drm_bridge_mode_fixup(bridge->next, mode, adjusted_mode);
+
+       return ret;
+}
+EXPORT_SYMBOL(drm_bridge_mode_fixup);
+
+/**
+ * drm_bridge_disable - calls 'disable' drm_bridge_funcs op for all
+ *                     bridges in the encoder chain.
+ * @bridge: bridge control structure
+ *
+ * Calls 'disable' drm_bridge_funcs op for all the bridges in the encoder
+ * chain, starting from the last bridge to the first. These are called before
+ * calling the encoder's prepare op.
+ *
+ * Note: the bridge passed should be the one closest to the encoder
+ */
+void drm_bridge_disable(struct drm_bridge *bridge)
+{
+       if (!bridge)
+               return;
+
+       drm_bridge_disable(bridge->next);
+
+       bridge->funcs->disable(bridge);
+}
+EXPORT_SYMBOL(drm_bridge_disable);
+
+/**
+ * drm_bridge_post_disable - calls 'post_disable' drm_bridge_funcs op for
+ *                          all bridges in the encoder chain.
+ * @bridge: bridge control structure
+ *
+ * Calls 'post_disable' drm_bridge_funcs op for all the bridges in the
+ * encoder chain, starting from the first bridge to the last. These are called
+ * after completing the encoder's prepare op.
+ *
+ * Note: the bridge passed should be the one closest to the encoder
+ */
+void drm_bridge_post_disable(struct drm_bridge *bridge)
+{
+       if (!bridge)
+               return;
+
+       bridge->funcs->post_disable(bridge);
+
+       drm_bridge_post_disable(bridge->next);
+}
+EXPORT_SYMBOL(drm_bridge_post_disable);
+
+/**
+ * drm_bridge_mode_set - set proposed mode for all bridges in the
+ *                      encoder chain
+ * @bridge: bridge control structure
+ * @mode: desired mode to be set for the bridge
+ * @adjusted_mode: updated mode that works for this bridge
+ *
+ * Calls 'mode_set' drm_bridge_funcs op for all the bridges in the
+ * encoder chain, starting from the first bridge to the last.
+ *
+ * Note: the bridge passed should be the one closest to the encoder
+ */
+void drm_bridge_mode_set(struct drm_bridge *bridge,
+                       struct drm_display_mode *mode,
+                       struct drm_display_mode *adjusted_mode)
+{
+       if (!bridge)
+               return;
+
+       if (bridge->funcs->mode_set)
+               bridge->funcs->mode_set(bridge, mode, adjusted_mode);
+
+       drm_bridge_mode_set(bridge->next, mode, adjusted_mode);
+}
+EXPORT_SYMBOL(drm_bridge_mode_set);
+
+/**
+ * drm_bridge_pre_enable - calls 'pre_enable' drm_bridge_funcs op for all
+ *                        bridges in the encoder chain.
+ * @bridge: bridge control structure
+ *
+ * Calls 'pre_enable' drm_bridge_funcs op for all the bridges in the encoder
+ * chain, starting from the last bridge to the first. These are called
+ * before calling the encoder's commit op.
+ *
+ * Note: the bridge passed should be the one closest to the encoder
+ */
+void drm_bridge_pre_enable(struct drm_bridge *bridge)
+{
+       if (!bridge)
+               return;
+
+       drm_bridge_pre_enable(bridge->next);
+
+       bridge->funcs->pre_enable(bridge);
+}
+EXPORT_SYMBOL(drm_bridge_pre_enable);
+
+/**
+ * drm_bridge_enable - calls 'enable' drm_bridge_funcs op for all bridges
+ *                    in the encoder chain.
+ * @bridge: bridge control structure
+ *
+ * Calls 'enable' drm_bridge_funcs op for all the bridges in the encoder
+ * chain, starting from the first bridge to the last. These are called
+ * after completing the encoder's commit op.
+ *
+ * Note that the bridge passed should be the one closest to the encoder
+ */
+void drm_bridge_enable(struct drm_bridge *bridge)
+{
+       if (!bridge)
+               return;
+
+       bridge->funcs->enable(bridge);
+
+       drm_bridge_enable(bridge->next);
+}
+EXPORT_SYMBOL(drm_bridge_enable);
+
 #ifdef CONFIG_OF
 struct drm_bridge *of_drm_find_bridge(struct device_node *np)
 {
 
 {
        const struct drm_encoder_helper_funcs *encoder_funcs = encoder->helper_private;
 
-       if (encoder->bridge)
-               encoder->bridge->funcs->disable(encoder->bridge);
+       drm_bridge_disable(encoder->bridge);
 
        if (encoder_funcs->disable)
                (*encoder_funcs->disable)(encoder);
        else
                (*encoder_funcs->dpms)(encoder, DRM_MODE_DPMS_OFF);
 
-       if (encoder->bridge)
-               encoder->bridge->funcs->post_disable(encoder->bridge);
+       drm_bridge_post_disable(encoder->bridge);
 }
 
 static void __drm_helper_disable_unused_functions(struct drm_device *dev)
                if (encoder->crtc != crtc)
                        continue;
 
-               if (encoder->bridge && encoder->bridge->funcs->mode_fixup) {
-                       ret = encoder->bridge->funcs->mode_fixup(
-                                       encoder->bridge, mode, adjusted_mode);
-                       if (!ret) {
-                               DRM_DEBUG_KMS("Bridge fixup failed\n");
-                               goto done;
-                       }
+               ret = drm_bridge_mode_fixup(encoder->bridge,
+                       mode, adjusted_mode);
+               if (!ret) {
+                       DRM_DEBUG_KMS("Bridge fixup failed\n");
+                       goto done;
                }
 
                encoder_funcs = encoder->helper_private;
                if (encoder->crtc != crtc)
                        continue;
 
-               if (encoder->bridge)
-                       encoder->bridge->funcs->disable(encoder->bridge);
+               drm_bridge_disable(encoder->bridge);
 
                encoder_funcs = encoder->helper_private;
                /* Disable the encoders as the first thing we do. */
                encoder_funcs->prepare(encoder);
 
-               if (encoder->bridge)
-                       encoder->bridge->funcs->post_disable(encoder->bridge);
+               drm_bridge_post_disable(encoder->bridge);
        }
 
        drm_crtc_prepare_encoders(dev);
                encoder_funcs = encoder->helper_private;
                encoder_funcs->mode_set(encoder, mode, adjusted_mode);
 
-               if (encoder->bridge && encoder->bridge->funcs->mode_set)
-                       encoder->bridge->funcs->mode_set(encoder->bridge, mode,
-                                       adjusted_mode);
+               drm_bridge_mode_set(encoder->bridge, mode, adjusted_mode);
        }
 
        /* Now enable the clocks, plane, pipe, and connectors that we set up. */
                if (encoder->crtc != crtc)
                        continue;
 
-               if (encoder->bridge)
-                       encoder->bridge->funcs->pre_enable(encoder->bridge);
+               drm_bridge_pre_enable(encoder->bridge);
 
                encoder_funcs = encoder->helper_private;
                encoder_funcs->commit(encoder);
 
-               if (encoder->bridge)
-                       encoder->bridge->funcs->enable(encoder->bridge);
+               drm_bridge_enable(encoder->bridge);
        }
 
        /* Calculate and store various constants which
        struct drm_bridge *bridge = encoder->bridge;
        const struct drm_encoder_helper_funcs *encoder_funcs;
 
-       if (bridge) {
-               if (mode == DRM_MODE_DPMS_ON)
-                       bridge->funcs->pre_enable(bridge);
-               else
-                       bridge->funcs->disable(bridge);
-       }
+       if (mode == DRM_MODE_DPMS_ON)
+               drm_bridge_pre_enable(bridge);
+       else
+               drm_bridge_disable(bridge);
 
        encoder_funcs = encoder->helper_private;
        if (encoder_funcs->dpms)
                encoder_funcs->dpms(encoder, mode);
 
-       if (bridge) {
-               if (mode == DRM_MODE_DPMS_ON)
-                       bridge->funcs->enable(bridge);
-               else
-                       bridge->funcs->post_disable(bridge);
-       }
+       if (mode == DRM_MODE_DPMS_ON)
+               drm_bridge_enable(bridge);
+       else
+               drm_bridge_post_disable(bridge);
 }
 
 static int drm_helper_choose_crtc_dpms(struct drm_crtc *crtc)
 
 /**
  * struct drm_bridge - central DRM bridge control structure
  * @dev: DRM device this bridge belongs to
+ * @encoder: encoder to which this bridge is connected
+ * @next: the next bridge in the encoder chain
  * @of_node: device node pointer to the bridge
  * @list: to keep track of all added bridges
  * @base: base mode object
 struct drm_bridge {
        struct drm_device *dev;
        struct drm_encoder *encoder;
+       struct drm_bridge *next;
 #ifdef CONFIG_OF
        struct device_node *of_node;
 #endif
 extern struct drm_bridge *of_drm_find_bridge(struct device_node *np);
 extern int drm_bridge_attach(struct drm_device *dev, struct drm_bridge *bridge);
 
+bool drm_bridge_mode_fixup(struct drm_bridge *bridge,
+                       const struct drm_display_mode *mode,
+                       struct drm_display_mode *adjusted_mode);
+void drm_bridge_disable(struct drm_bridge *bridge);
+void drm_bridge_post_disable(struct drm_bridge *bridge);
+void drm_bridge_mode_set(struct drm_bridge *bridge,
+                       struct drm_display_mode *mode,
+                       struct drm_display_mode *adjusted_mode);
+void drm_bridge_pre_enable(struct drm_bridge *bridge);
+void drm_bridge_enable(struct drm_bridge *bridge);
+
 extern int drm_encoder_init(struct drm_device *dev,
                            struct drm_encoder *encoder,
                            const struct drm_encoder_funcs *funcs,