On Tue, Oct 28, 2014 at 1:41 AM, Sean Paul <seanpaul@xxxxxxxxxxxx> wrote: > 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