drm_info.o drm_debugfs.o drm_encoder_slave.o \
                drm_trace_points.o drm_global.o drm_prime.o \
                drm_rect.o drm_vma_manager.o drm_flip_work.o \
-               drm_modeset_lock.o drm_atomic.o
+               drm_modeset_lock.o drm_atomic.o drm_bridge.o
 
 drm-$(CONFIG_COMPAT) += drm_ioc32.o
 drm-$(CONFIG_DRM_GEM_CMA_HELPER) += drm_gem_cma_helper.o
 
 {
 }
 
-static void ptn3460_bridge_destroy(struct drm_bridge *bridge)
-{
-       struct ptn3460_bridge *ptn_bridge = bridge_to_ptn3460(bridge);
-
-       drm_bridge_cleanup(bridge);
-       if (gpio_is_valid(ptn_bridge->gpio_pd_n))
-               gpio_free(ptn_bridge->gpio_pd_n);
-       if (gpio_is_valid(ptn_bridge->gpio_rst_n))
-               gpio_free(ptn_bridge->gpio_rst_n);
-       /* Nothing else to free, we've got devm allocated memory */
-}
-
 static struct drm_bridge_funcs ptn3460_bridge_funcs = {
        .pre_enable = ptn3460_pre_enable,
        .enable = ptn3460_enable,
        .disable = ptn3460_disable,
        .post_disable = ptn3460_post_disable,
-       .destroy = ptn3460_bridge_destroy,
 };
 
 static int ptn3460_get_modes(struct drm_connector *connector)
        }
 
        ptn_bridge->bridge.funcs = &ptn3460_bridge_funcs;
-       ret = drm_bridge_init(dev, &ptn_bridge->bridge);
+       ret = drm_bridge_attach(dev, &ptn_bridge->bridge);
        if (ret) {
                DRM_ERROR("Failed to initialize bridge with drm\n");
                goto err;
        return ret;
 }
 EXPORT_SYMBOL(ptn3460_init);
+
+void ptn3460_destroy(struct drm_bridge *bridge)
+{
+       struct ptn3460_bridge *ptn_bridge = bridge->driver_private;
+
+       if (gpio_is_valid(ptn_bridge->gpio_pd_n))
+               gpio_free(ptn_bridge->gpio_pd_n);
+       if (gpio_is_valid(ptn_bridge->gpio_rst_n))
+               gpio_free(ptn_bridge->gpio_rst_n);
+       /* Nothing else to free, we've got devm allocated memory */
+}
+EXPORT_SYMBOL(ptn3460_destroy);
 
--- /dev/null
+/*
+ * Copyright (c) 2014 Samsung Electronics Co., Ltd
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sub license,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ */
+
+#include <linux/err.h>
+#include <linux/module.h>
+
+#include <drm/drm_crtc.h>
+
+#include "drm/drmP.h"
+
+static DEFINE_MUTEX(bridge_lock);
+static LIST_HEAD(bridge_list);
+
+int drm_bridge_add(struct drm_bridge *bridge)
+{
+       mutex_lock(&bridge_lock);
+       list_add_tail(&bridge->list, &bridge_list);
+       mutex_unlock(&bridge_lock);
+
+       return 0;
+}
+EXPORT_SYMBOL(drm_bridge_add);
+
+void drm_bridge_remove(struct drm_bridge *bridge)
+{
+       mutex_lock(&bridge_lock);
+       list_del_init(&bridge->list);
+       mutex_unlock(&bridge_lock);
+}
+EXPORT_SYMBOL(drm_bridge_remove);
+
+extern int drm_bridge_attach(struct drm_device *dev, struct drm_bridge *bridge)
+{
+       if (!dev || !bridge)
+               return -EINVAL;
+
+       if (bridge->dev)
+               return -EBUSY;
+
+       bridge->dev = dev;
+
+       if (bridge->funcs->attach)
+               return bridge->funcs->attach(bridge);
+
+       return 0;
+}
+EXPORT_SYMBOL(drm_bridge_attach);
+
+#ifdef CONFIG_OF
+struct drm_bridge *of_drm_find_bridge(struct device_node *np)
+{
+       struct drm_bridge *bridge;
+
+       mutex_lock(&bridge_lock);
+
+       list_for_each_entry(bridge, &bridge_list, list) {
+               if (bridge->of_node == np) {
+                       mutex_unlock(&bridge_lock);
+                       return bridge;
+               }
+       }
+
+       mutex_unlock(&bridge_lock);
+       return NULL;
+}
+EXPORT_SYMBOL(of_drm_find_bridge);
+#endif
+
+MODULE_AUTHOR("Ajay Kumar <ajaykumar.rs@samsung.com>");
+MODULE_DESCRIPTION("DRM bridge infrastructure");
+MODULE_LICENSE("GPL and additional rights");
 
 }
 EXPORT_SYMBOL(drm_connector_unplug_all);
 
-/**
- * drm_bridge_init - initialize a drm transcoder/bridge
- * @dev: drm device
- * @bridge: transcoder/bridge to set up
- *
- * Initialises a preallocated bridge. Bridges should be
- * subclassed as part of driver connector objects.
- *
- * Returns:
- * Zero on success, error code on failure.
- */
-int drm_bridge_init(struct drm_device *dev, struct drm_bridge *bridge)
-{
-       int ret;
-
-       drm_modeset_lock_all(dev);
-
-       ret = drm_mode_object_get(dev, &bridge->base, DRM_MODE_OBJECT_BRIDGE);
-       if (ret)
-               goto out;
-
-       bridge->dev = dev;
-
-       list_add_tail(&bridge->head, &dev->mode_config.bridge_list);
-       dev->mode_config.num_bridge++;
-
- out:
-       drm_modeset_unlock_all(dev);
-       return ret;
-}
-EXPORT_SYMBOL(drm_bridge_init);
-
-/**
- * drm_bridge_cleanup - cleans up an initialised bridge
- * @bridge: bridge to cleanup
- *
- * Cleans up the bridge but doesn't free the object.
- */
-void drm_bridge_cleanup(struct drm_bridge *bridge)
-{
-       struct drm_device *dev = bridge->dev;
-
-       drm_modeset_lock_all(dev);
-       drm_mode_object_put(dev, &bridge->base);
-       list_del(&bridge->head);
-       dev->mode_config.num_bridge--;
-       drm_modeset_unlock_all(dev);
-
-       memset(bridge, 0, sizeof(*bridge));
-}
-EXPORT_SYMBOL(drm_bridge_cleanup);
-
 /**
  * drm_encoder_init - Init a preallocated encoder
  * @dev: drm device
        total_objects += dev->mode_config.num_crtc;
        total_objects += dev->mode_config.num_connector;
        total_objects += dev->mode_config.num_encoder;
-       total_objects += dev->mode_config.num_bridge;
 
        group->id_list = kcalloc(total_objects, sizeof(uint32_t), GFP_KERNEL);
        if (!group->id_list)
        group->num_crtcs = 0;
        group->num_connectors = 0;
        group->num_encoders = 0;
-       group->num_bridges = 0;
        return 0;
 }
 
        struct drm_crtc *crtc;
        struct drm_encoder *encoder;
        struct drm_connector *connector;
-       struct drm_bridge *bridge;
        int ret;
 
        ret = drm_mode_group_init(dev, group);
                group->id_list[group->num_crtcs + group->num_encoders +
                               group->num_connectors++] = connector->base.id;
 
-       list_for_each_entry(bridge, &dev->mode_config.bridge_list, head)
-               group->id_list[group->num_crtcs + group->num_encoders +
-                              group->num_connectors + group->num_bridges++] =
-                                       bridge->base.id;
-
        return 0;
 }
 EXPORT_SYMBOL(drm_mode_group_init_legacy_group);
        INIT_LIST_HEAD(&dev->mode_config.fb_list);
        INIT_LIST_HEAD(&dev->mode_config.crtc_list);
        INIT_LIST_HEAD(&dev->mode_config.connector_list);
-       INIT_LIST_HEAD(&dev->mode_config.bridge_list);
        INIT_LIST_HEAD(&dev->mode_config.encoder_list);
        INIT_LIST_HEAD(&dev->mode_config.property_list);
        INIT_LIST_HEAD(&dev->mode_config.property_blob_list);
        struct drm_connector *connector, *ot;
        struct drm_crtc *crtc, *ct;
        struct drm_encoder *encoder, *enct;
-       struct drm_bridge *bridge, *brt;
        struct drm_framebuffer *fb, *fbt;
        struct drm_property *property, *pt;
        struct drm_property_blob *blob, *bt;
                encoder->funcs->destroy(encoder);
        }
 
-       list_for_each_entry_safe(bridge, brt,
-                                &dev->mode_config.bridge_list, head) {
-               bridge->funcs->destroy(bridge);
-       }
-
        list_for_each_entry_safe(connector, ot,
                                 &dev->mode_config.connector_list, head) {
                connector->funcs->destroy(connector);
 
        return 0;
 
 fail:
-       /* bridge/connector are normally destroyed by drm: */
+       /* bridge is normally destroyed by drm: */
        if (hdmi->bridge) {
-               hdmi->bridge->funcs->destroy(hdmi->bridge);
+               hdmi_bridge_destroy(hdmi->bridge);
                hdmi->bridge = NULL;
        }
        if (hdmi->connector) {
 
  */
 
 struct drm_bridge *hdmi_bridge_init(struct hdmi *hdmi);
+void hdmi_bridge_destroy(struct drm_bridge *bridge);
 
 /*
  * hdmi connector:
 
 };
 #define to_hdmi_bridge(x) container_of(x, struct hdmi_bridge, base)
 
-static void hdmi_bridge_destroy(struct drm_bridge *bridge)
+void hdmi_bridge_destroy(struct drm_bridge *bridge)
 {
        struct hdmi_bridge *hdmi_bridge = to_hdmi_bridge(bridge);
-       drm_bridge_cleanup(bridge);
        kfree(hdmi_bridge);
 }
 
                .disable = hdmi_bridge_disable,
                .post_disable = hdmi_bridge_post_disable,
                .mode_set = hdmi_bridge_mode_set,
-               .destroy = hdmi_bridge_destroy,
 };
 
 
        bridge = &hdmi_bridge->base;
        bridge->funcs = &hdmi_bridge_funcs;
 
-       drm_bridge_init(hdmi->dev, bridge);
+       drm_bridge_attach(hdmi->dev, bridge);
 
        return bridge;
 
 
        /* do nothing */
 }
 
-static void sti_hda_brigde_destroy(struct drm_bridge *bridge)
-{
-       drm_bridge_cleanup(bridge);
-       kfree(bridge);
-}
-
 static const struct drm_bridge_funcs sti_hda_bridge_funcs = {
        .pre_enable = sti_hda_pre_enable,
        .enable = sti_hda_bridge_nope,
        .disable = sti_hda_disable,
        .post_disable = sti_hda_bridge_nope,
        .mode_set = sti_hda_set_mode,
-       .destroy = sti_hda_brigde_destroy,
 };
 
 static int sti_hda_connector_get_modes(struct drm_connector *connector)
 
        bridge->driver_private = hda;
        bridge->funcs = &sti_hda_bridge_funcs;
-       drm_bridge_init(drm_dev, bridge);
+       drm_bridge_attach(drm_dev, bridge);
 
        encoder->bridge = bridge;
        connector->encoder = encoder;
 err_sysfs:
        drm_connector_unregister(drm_connector);
 err_connector:
-       drm_bridge_cleanup(bridge);
        drm_connector_cleanup(drm_connector);
        return -EINVAL;
 }
 
        /* do nothing */
 }
 
-static void sti_hdmi_brigde_destroy(struct drm_bridge *bridge)
-{
-       drm_bridge_cleanup(bridge);
-       kfree(bridge);
-}
-
 static const struct drm_bridge_funcs sti_hdmi_bridge_funcs = {
        .pre_enable = sti_hdmi_pre_enable,
        .enable = sti_hdmi_bridge_nope,
        .disable = sti_hdmi_disable,
        .post_disable = sti_hdmi_bridge_nope,
        .mode_set = sti_hdmi_set_mode,
-       .destroy = sti_hdmi_brigde_destroy,
 };
 
 static int sti_hdmi_connector_get_modes(struct drm_connector *connector)
 
        bridge->driver_private = hdmi;
        bridge->funcs = &sti_hdmi_bridge_funcs;
-       drm_bridge_init(drm_dev, bridge);
+       drm_bridge_attach(drm_dev, bridge);
 
        encoder->bridge = bridge;
        connector->encoder = encoder;
 err_sysfs:
        drm_connector_unregister(drm_connector);
 err_connector:
-       drm_bridge_cleanup(bridge);
        drm_connector_cleanup(drm_connector);
 err_adapt:
        put_device(&hdmi->ddc_adapt->dev);
 
 #define _DRM_BRIDGE_PTN3460_H_
 
 struct drm_device;
+struct drm_bridge;
 struct drm_encoder;
 struct i2c_client;
 struct device_node;
 
 int ptn3460_init(struct drm_device *dev, struct drm_encoder *encoder,
                struct i2c_client *client, struct device_node *node);
+
+void ptn3460_destroy(struct drm_bridge *bridge);
+
 #else
 
 static inline int ptn3460_init(struct drm_device *dev,
        return 0;
 }
 
+static inline void ptn3460_destroy(struct drm_bridge *bridge)
+{
+}
+
 #endif
 
 #endif
 
 
 /**
  * struct drm_bridge_funcs - drm_bridge control functions
+ * @attach: Called during drm_bridge_attach
  * @mode_fixup: Try to fixup (or reject entirely) proposed mode for this bridge
  * @disable: Called right before encoder prepare, disables the bridge
  * @post_disable: Called right after encoder prepare, for lockstepped disable
  * @mode_set: Set this mode to the bridge
  * @pre_enable: Called right before encoder commit, for lockstepped commit
  * @enable: Called right after encoder commit, enables the bridge
- * @destroy: make object go away
  */
 struct drm_bridge_funcs {
+       int (*attach)(struct drm_bridge *bridge);
        bool (*mode_fixup)(struct drm_bridge *bridge,
                           const struct drm_display_mode *mode,
                           struct drm_display_mode *adjusted_mode);
                         struct drm_display_mode *adjusted_mode);
        void (*pre_enable)(struct drm_bridge *bridge);
        void (*enable)(struct drm_bridge *bridge);
-       void (*destroy)(struct drm_bridge *bridge);
 };
 
 /**
  * struct drm_bridge - central DRM bridge control structure
  * @dev: DRM device this bridge belongs to
- * @head: list management
+ * @of_node: device node pointer to the bridge
+ * @list: to keep track of all added bridges
  * @base: base mode object
  * @funcs: control functions
  * @driver_private: pointer to the bridge driver's internal context
  */
 struct drm_bridge {
        struct drm_device *dev;
-       struct list_head head;
-
-       struct drm_mode_object base;
+       struct drm_encoder *encoder;
+#ifdef CONFIG_OF
+       struct device_node *of_node;
+#endif
+       struct list_head list;
 
        const struct drm_bridge_funcs *funcs;
        void *driver_private;
        uint32_t num_crtcs;
        uint32_t num_encoders;
        uint32_t num_connectors;
-       uint32_t num_bridges;
 
        /* list of object IDs for this group */
        uint32_t *id_list;
  * @fb_list: list of framebuffers available
  * @num_connector: number of connectors on this device
  * @connector_list: list of connector objects
- * @num_bridge: number of bridges on this device
- * @bridge_list: list of bridge objects
  * @num_encoder: number of encoders on this device
  * @encoder_list: list of encoder objects
  * @num_overlay_plane: number of overlay planes on this device
 
        int num_connector;
        struct list_head connector_list;
-       int num_bridge;
-       struct list_head bridge_list;
        int num_encoder;
        struct list_head encoder_list;
 
 /* helper to unplug all connectors from sysfs for device */
 extern void drm_connector_unplug_all(struct drm_device *dev);
 
-extern int drm_bridge_init(struct drm_device *dev, struct drm_bridge *bridge);
-extern void drm_bridge_cleanup(struct drm_bridge *bridge);
+extern int drm_bridge_add(struct drm_bridge *bridge);
+extern void drm_bridge_remove(struct drm_bridge *bridge);
+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);
 
 extern int drm_encoder_init(struct drm_device *dev,
                            struct drm_encoder *encoder,