On Wed, Aug 27, 2014 at 10:29 AM, Ajay Kumar <ajaykumar.rs@xxxxxxxxxxx> wrote: > A set of helper functions are defined in this patch to make > bridge driver probe independent of the drm flow. > > The bridge devices register themselves on a lookup table > when they get probed by calling "drm_bridge_add". > > The parent encoder driver waits till the bridge is available > in the lookup table(by calling "of_drm_find_bridge") and then > continues with its initialization. > > The encoder driver should also call "drm_bridge_attach" to pass > on the drm_device, encoder pointers to the bridge object. > > drm_bridge_attach inturn calls drm_bridge_init to register itself > with the drm core. Later, it calls "bridge->funcs->attach" so that > bridge can continue with other initializations. > > Signed-off-by: Ajay Kumar <ajaykumar.rs@xxxxxxxxxxx> > --- > drivers/gpu/drm/Makefile | 1 + > drivers/gpu/drm/bridge/Kconfig | 15 ++++- > drivers/gpu/drm/drm_bridge.c | 102 ++++++++++++++++++++++++++++++++ > drivers/gpu/drm/drm_crtc.c | 4 +- > drivers/gpu/drm/msm/hdmi/hdmi_bridge.c | 4 +- > include/drm/drm_crtc.h | 12 +++- > 6 files changed, 131 insertions(+), 7 deletions(-) > create mode 100644 drivers/gpu/drm/drm_bridge.c > > diff --git a/drivers/gpu/drm/Makefile b/drivers/gpu/drm/Makefile > index 4a55d59..bdbfb6f 100644 > --- a/drivers/gpu/drm/Makefile > +++ b/drivers/gpu/drm/Makefile > @@ -19,6 +19,7 @@ drm-y := drm_auth.o drm_buffer.o drm_bufs.o drm_cache.o \ > drm-$(CONFIG_COMPAT) += drm_ioc32.o > drm-$(CONFIG_DRM_GEM_CMA_HELPER) += drm_gem_cma_helper.o > drm-$(CONFIG_PCI) += ati_pcigart.o > +drm-$(CONFIG_DRM_BRIDGE) += drm_bridge.o > drm-$(CONFIG_DRM_PANEL) += drm_panel.o > drm-$(CONFIG_OF) += drm_of.o > > diff --git a/drivers/gpu/drm/bridge/Kconfig b/drivers/gpu/drm/bridge/Kconfig > index 884923f..5a8e907 100644 > --- a/drivers/gpu/drm/bridge/Kconfig > +++ b/drivers/gpu/drm/bridge/Kconfig > @@ -1,5 +1,16 @@ > -config DRM_PTN3460 > - tristate "PTN3460 DP/LVDS bridge" > +config DRM_BRIDGE I'm not convinced this adds any value, to be honest. In addition to whether or not it's useful, it seems like you'd need to stub the drm_bridge_* functions that are declared in drm_crtc.h or break them out into drm_bridge.h. Sean > + tristate > depends on DRM > select DRM_KMS_HELPER > + help > + Bridge registration and lookup framework. > + > +menu "bridge chips" > + depends on DRM_BRIDGE > + > +config DRM_PTN3460 > + tristate "PTN3460 DP/LVDS bridge" > + depends on DRM_BRIDGE > ---help--- > + > +endmenu > diff --git a/drivers/gpu/drm/drm_bridge.c b/drivers/gpu/drm/drm_bridge.c > new file mode 100644 > index 0000000..b2d43fd > --- /dev/null > +++ b/drivers/gpu/drm/drm_bridge.c > @@ -0,0 +1,102 @@ > +/* > + * 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); > + > +int drm_bridge_attach(struct drm_bridge *bridge, > + struct drm_encoder *encoder) > +{ > + int ret; > + > + if (!bridge || !encoder) > + return -EINVAL; > + > + if (bridge->encoder) > + return -EBUSY; > + > + encoder->bridge = bridge; > + bridge->encoder = encoder; > + bridge->drm = encoder->dev; > + > + ret = drm_bridge_init(bridge->drm, bridge); > + if (ret) { > + DRM_ERROR("Failed to register bridge with drm\n"); > + return ret; > + } > + > + 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->dev->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@xxxxxxxxxxx>"); > +MODULE_DESCRIPTION("DRM bridge infrastructure"); > +MODULE_LICENSE("GPL and additional rights"); > diff --git a/drivers/gpu/drm/drm_crtc.c b/drivers/gpu/drm/drm_crtc.c > index 25f5cfa..2fb22fa 100644 > --- a/drivers/gpu/drm/drm_crtc.c > +++ b/drivers/gpu/drm/drm_crtc.c > @@ -1039,7 +1039,7 @@ int drm_bridge_init(struct drm_device *dev, struct drm_bridge *bridge) > if (ret) > goto out; > > - bridge->dev = dev; > + bridge->drm = dev; > > list_add_tail(&bridge->head, &dev->mode_config.bridge_list); > dev->mode_config.num_bridge++; > @@ -1058,7 +1058,7 @@ EXPORT_SYMBOL(drm_bridge_init); > */ > void drm_bridge_cleanup(struct drm_bridge *bridge) > { > - struct drm_device *dev = bridge->dev; > + struct drm_device *dev = bridge->drm; > > drm_modeset_lock_all(dev); > drm_mode_object_put(dev, &bridge->base); > diff --git a/drivers/gpu/drm/msm/hdmi/hdmi_bridge.c b/drivers/gpu/drm/msm/hdmi/hdmi_bridge.c > index 0309539..bc9e5ff 100644 > --- a/drivers/gpu/drm/msm/hdmi/hdmi_bridge.c > +++ b/drivers/gpu/drm/msm/hdmi/hdmi_bridge.c > @@ -33,7 +33,7 @@ static void hdmi_bridge_destroy(struct drm_bridge *bridge) > > static void power_on(struct drm_bridge *bridge) > { > - struct drm_device *dev = bridge->dev; > + struct drm_device *dev = bridge->drm; > struct hdmi_bridge *hdmi_bridge = to_hdmi_bridge(bridge); > struct hdmi *hdmi = hdmi_bridge->hdmi; > const struct hdmi_platform_config *config = hdmi->config; > @@ -67,7 +67,7 @@ static void power_on(struct drm_bridge *bridge) > > static void power_off(struct drm_bridge *bridge) > { > - struct drm_device *dev = bridge->dev; > + struct drm_device *dev = bridge->drm; > struct hdmi_bridge *hdmi_bridge = to_hdmi_bridge(bridge); > struct hdmi *hdmi = hdmi_bridge->hdmi; > const struct hdmi_platform_config *config = hdmi->config; > diff --git a/include/drm/drm_crtc.h b/include/drm/drm_crtc.h > index f48a436..f6f426f 100644 > --- a/include/drm/drm_crtc.h > +++ b/include/drm/drm_crtc.h > @@ -629,6 +629,7 @@ struct drm_plane { > > /** > * 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 > @@ -638,6 +639,7 @@ struct drm_plane { > * @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); > @@ -660,8 +662,11 @@ struct drm_bridge_funcs { > * @driver_private: pointer to the bridge driver's internal context > */ > struct drm_bridge { > - struct drm_device *dev; > + struct device *dev; > + struct drm_device *drm; > + struct drm_encoder *encoder; > struct list_head head; > + struct list_head list; > > struct drm_mode_object base; > > @@ -906,6 +911,11 @@ extern void drm_connector_cleanup(struct drm_connector *connector); > /* helper to unplug all connectors from sysfs for device */ > extern void drm_connector_unplug_all(struct drm_device *dev); > > +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_bridge *bridge, > + struct drm_encoder *encoder); > extern int drm_bridge_init(struct drm_device *dev, struct drm_bridge *bridge); > extern void drm_bridge_cleanup(struct drm_bridge *bridge); > > -- > 1.7.9.5 > > -- > To unsubscribe from this list: send the line "unsubscribe linux-samsung-soc" in > the body of a message to majordomo@xxxxxxxxxxxxxxx > More majordomo info at http://vger.kernel.org/majordomo-info.html -- To unsubscribe from this list: send the line "unsubscribe linux-samsung-soc" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html