// SPDX-License-Identifier: GPL-2.0+ /* * Freescale i.MX drm driver * * bridge driver for legacy DT bindings, utilizing display-timings node */ #include <drm/drm_bridge.h> #include <drm/drm_modes.h> #include <drm/drm_probe_helper.h> #include <drm/bridge/imx.h> #include <video/of_display_timing.h> #include <video/of_videomode.h> struct imx_legacy_bridge { struct drm_bridge base; struct drm_display_mode mode; u32 bus_flags; }; #define to_imx_legacy_bridge(bridge) container_of(bridge, struct imx_legacy_bridge, base) static int imx_legacy_bridge_attach(struct drm_bridge *bridge, enum drm_bridge_attach_flags flags) { if (!(flags & DRM_BRIDGE_ATTACH_NO_CONNECTOR)) return -EINVAL; return 0; } static int imx_legacy_bridge_get_modes(struct drm_bridge *bridge, struct drm_connector *connector) { struct imx_legacy_bridge *imx_bridge = to_imx_legacy_bridge(bridge); int ret; ret = drm_connector_helper_get_modes_fixed(connector, &imx_bridge->mode); if (ret) return ret; connector->display_info.bus_flags = imx_bridge->bus_flags; return 0; } struct drm_bridge_funcs imx_legacy_bridge_funcs = { .attach = imx_legacy_bridge_attach, .get_modes = imx_legacy_bridge_get_modes, }; struct drm_bridge *devm_imx_drm_legacy_bridge(struct device *dev, struct device_node *np, int type) { struct imx_legacy_bridge *imx_bridge; int ret; imx_bridge = devm_kzalloc(dev, sizeof(*imx_bridge), GFP_KERNEL); if (!imx_bridge) return ERR_PTR(-ENOMEM); ret = of_get_drm_display_mode(np, &imx_bridge->mode, &imx_bridge->bus_flags, OF_USE_NATIVE_MODE); if (ret) return ERR_PTR(ret); imx_bridge->mode.type |= DRM_MODE_TYPE_DRIVER; imx_bridge->base.funcs = &imx_legacy_bridge_funcs; imx_bridge->base.of_node = np; imx_bridge->base.ops = DRM_BRIDGE_OP_MODES; imx_bridge->base.type = type; ret = devm_drm_bridge_add(dev, &imx_bridge->base); if (ret) return ERR_PTR(ret); return &imx_bridge->base; } EXPORT_SYMBOL_GPL(devm_imx_drm_legacy_bridge); MODULE_LICENSE("GPL"); MODULE_DESCRIPTION("Freescale i.MX DRM bridge driver for legacy DT bindings");