Signed-off-by: Rob Clark <robdclark@xxxxxxxxx> --- drivers/gpu/drm/bridge/Makefile | 2 + drivers/gpu/drm/bridge/drm_bridge_util.c | 251 +++++++++++++++++++++++++++++++ drivers/gpu/drm/bridge/drm_bridge_util.h | 29 ++++ 3 files changed, 282 insertions(+) create mode 100644 drivers/gpu/drm/bridge/drm_bridge_util.c create mode 100644 drivers/gpu/drm/bridge/drm_bridge_util.h diff --git a/drivers/gpu/drm/bridge/Makefile b/drivers/gpu/drm/bridge/Makefile index b4733e1..da6b301 100644 --- a/drivers/gpu/drm/bridge/Makefile +++ b/drivers/gpu/drm/bridge/Makefile @@ -1,3 +1,5 @@ ccflags-y := -Iinclude/drm obj-$(CONFIG_DRM_PTN3460) += ptn3460.o +# TODO kconfig for drivers who use this to select it.. +obj-y += drm_bridge_util.o \ No newline at end of file diff --git a/drivers/gpu/drm/bridge/drm_bridge_util.c b/drivers/gpu/drm/bridge/drm_bridge_util.c new file mode 100644 index 0000000..89964b2 --- /dev/null +++ b/drivers/gpu/drm/bridge/drm_bridge_util.c @@ -0,0 +1,251 @@ +/* + * Copyright (C) 2014 Red Hat + * Author: Rob Clark <robdclark@xxxxxxxxx> + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 as published by + * the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License along with + * this program. If not, see <http://www.gnu.org/licenses/>. + */ + +#include "drm_bridge_util.h" + +/* + * Composite Bridge: + */ + +/** + * drm_composite_bridge - helper bridge class to construct a graph + * with multiple actual bridges + */ +struct drm_composite_bridge { + struct drm_bridge base; + struct drm_bridge *b1, *b2; +}; +#define to_composite_bridge(x) container_of(x, struct drm_composite_bridge, base) + +static bool +composite_bridge_mode_fixup(struct drm_bridge *bridge, + const struct drm_display_mode *mode, + struct drm_display_mode *adjusted_mode) +{ + struct drm_composite_bridge *cbridge = to_composite_bridge(bridge); + struct drm_bridge *b1 = cbridge->b1; + struct drm_bridge *b2 = cbridge->b2; + + if (b1->funcs->mode_fixup) + if (!b1->funcs->mode_fixup(b1, mode, adjusted_mode)) + return false; + if (b2->funcs->mode_fixup) + if (!b2->funcs->mode_fixup(b2, mode, adjusted_mode)) + return false; + + return true; +} + +static void +composite_bridge_mode_set(struct drm_bridge *bridge, + struct drm_display_mode *mode, + struct drm_display_mode *adjusted_mode) +{ + struct drm_composite_bridge *cbridge = to_composite_bridge(bridge); + struct drm_bridge *b1 = cbridge->b1; + struct drm_bridge *b2 = cbridge->b2; + + if (b1->funcs->mode_set) + b1->funcs->mode_set(b1, mode, adjusted_mode); + if (b2->funcs->mode_set) + b2->funcs->mode_set(b2, mode, adjusted_mode); +} + +static void +composite_bridge_disable(struct drm_bridge *bridge) +{ + struct drm_composite_bridge *cbridge = to_composite_bridge(bridge); + struct drm_bridge *b1 = cbridge->b1; + struct drm_bridge *b2 = cbridge->b2; + + /* note: order inverted in disable path: */ + b2->funcs->disable(b2); + b1->funcs->disable(b1); +} + +static void +composite_bridge_post_disable(struct drm_bridge *bridge) +{ + struct drm_composite_bridge *cbridge = to_composite_bridge(bridge); + struct drm_bridge *b1 = cbridge->b1; + struct drm_bridge *b2 = cbridge->b2; + + /* note: order inverted in disable path: */ + b2->funcs->post_disable(b2); + b1->funcs->post_disable(b1); +} + +static void +composite_bridge_pre_enable(struct drm_bridge *bridge) +{ + struct drm_composite_bridge *cbridge = to_composite_bridge(bridge); + struct drm_bridge *b1 = cbridge->b1; + struct drm_bridge *b2 = cbridge->b2; + + b1->funcs->pre_enable(b1); + b2->funcs->pre_enable(b2); +} + +static void +composite_bridge_enable(struct drm_bridge *bridge) +{ + struct drm_composite_bridge *cbridge = to_composite_bridge(bridge); + struct drm_bridge *b1 = cbridge->b1; + struct drm_bridge *b2 = cbridge->b2; + + b1->funcs->enable(b1); + b2->funcs->enable(b2); +} + +static void +composite_bridge_destroy(struct drm_bridge *bridge) +{ + struct drm_composite_bridge *cbridge = to_composite_bridge(bridge); + struct drm_bridge *b1 = cbridge->b1; + struct drm_bridge *b2 = cbridge->b2; + + b1->funcs->destroy(b1); + b2->funcs->destroy(b2); + + kfree(cbridge); +} + +static const struct drm_bridge_funcs composite_bridge_funcs = { + .mode_fixup = composite_bridge_mode_fixup, + .disable = composite_bridge_disable, + .post_disable = composite_bridge_post_disable, + .mode_set = composite_bridge_mode_set, + .pre_enable = composite_bridge_pre_enable, + .enable = composite_bridge_enable, + .destroy = composite_bridge_destroy, +}; + +struct drm_bridge * drm_composite_bridge_init(struct drm_bridge *b1, + struct drm_bridge *b2) +{ + struct drm_bridge *bridge = NULL; + struct drm_composite_bridge *cbridge; + int ret; + + WARN_ON(b1->dev != b2->dev); + + cbridge = kzalloc(sizeof(*cbridge), GFP_KERNEL); + if (!cbridge) { + ret = -ENOMEM; + goto fail; + } + + bridge = &cbridge->base; + + cbridge->b1 = b1; + cbridge->b2 = b2; + + drm_bridge_init(b1->dev, bridge, &composite_bridge_funcs); + + return bridge; + +fail: + if (bridge) + composite_bridge_destroy(bridge); + + return ERR_PTR(ret); +} + +/* + * Panel Bridge: + */ + +/** + * drm_panel_bridge - helper to chain up a panel + */ +struct drm_panel_bridge { + struct drm_bridge base; + struct drm_panel *panel; +}; +#define to_panel_bridge(x) container_of(x, struct drm_panel_bridge, base) + +static void +panel_bridge_disable(struct drm_bridge *bridge) +{ + struct drm_panel_bridge *pbridge = to_panel_bridge(bridge); + drm_panel_disable(pbridge->panel); +} + +static void +panel_bridge_post_disable(struct drm_bridge *bridge) +{ +//TODO +// struct drm_panel_bridge *pbridge = to_panel_bridge(bridge); +// drm_panel_post_disable(pbridge->panel); +} + +static void +panel_bridge_pre_enable(struct drm_bridge *bridge) +{ +//TODO +// struct drm_panel_bridge *pbridge = to_panel_bridge(bridge); +// drm_panel_pre_enable(pbridge->panel); +} + +static void +panel_bridge_enable(struct drm_bridge *bridge) +{ + struct drm_panel_bridge *pbridge = to_panel_bridge(bridge); + drm_panel_enable(pbridge->panel); +} + +static void +panel_bridge_destroy(struct drm_bridge *bridge) +{ + struct drm_panel_bridge *pbridge = to_panel_bridge(bridge); + kfree(pbridge); +} + +static const struct drm_bridge_funcs panel_bridge_funcs = { + .disable = panel_bridge_disable, + .post_disable = panel_bridge_post_disable, + .pre_enable = panel_bridge_pre_enable, + .enable = panel_bridge_enable, + .destroy = panel_bridge_destroy, +}; + +struct drm_bridge * drm_panel_bridge_init(struct drm_panel *panel) +{ + struct drm_bridge *bridge = NULL; + struct drm_panel_bridge *pbridge; + int ret; + + pbridge = kzalloc(sizeof(*pbridge), GFP_KERNEL); + if (!pbridge) { + ret = -ENOMEM; + goto fail; + } + + bridge = &pbridge->base; + + pbridge->panel = panel; + + drm_bridge_init(panel->drm, bridge, &panel_bridge_funcs); + + return bridge; + +fail: + if (bridge) + panel_bridge_destroy(bridge); + + return ERR_PTR(ret); +} diff --git a/drivers/gpu/drm/bridge/drm_bridge_util.h b/drivers/gpu/drm/bridge/drm_bridge_util.h new file mode 100644 index 0000000..4f7a994 --- /dev/null +++ b/drivers/gpu/drm/bridge/drm_bridge_util.h @@ -0,0 +1,29 @@ +/* + * Copyright (C) 2014 Red Hat + * Author: Rob Clark <robdclark@xxxxxxxxx> + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 as published by + * the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License along with + * this program. If not, see <http://www.gnu.org/licenses/>. + */ + +#ifndef DRM_BRIDGE_UTIL_H_ +#define DRM_BRIDGE_UTIL_H_ + +#include "drmP.h" +#include "drm_crtc.h" +#include "drm_panel.h" + +struct drm_bridge * drm_composite_bridge_init(struct drm_bridge *b1, + struct drm_bridge *b2); +struct drm_bridge * drm_panel_bridge_init(struct drm_panel *panel); + +#endif /* DRM_BRIDGE_UTIL_H_ */ -- 1.9.0 _______________________________________________ dri-devel mailing list dri-devel@xxxxxxxxxxxxxxxxxxxxx http://lists.freedesktop.org/mailman/listinfo/dri-devel