1cc3e8a21SDmitry Baryshkov // SPDX-License-Identifier: GPL-2.0+ 2cc3e8a21SDmitry Baryshkov /* 3cc3e8a21SDmitry Baryshkov * Freescale i.MX drm driver 4cc3e8a21SDmitry Baryshkov * 5cc3e8a21SDmitry Baryshkov * bridge driver for legacy DT bindings, utilizing display-timings node 6cc3e8a21SDmitry Baryshkov */ 7cc3e8a21SDmitry Baryshkov 8cc3e8a21SDmitry Baryshkov #include <drm/drm_bridge.h> 9cc3e8a21SDmitry Baryshkov #include <drm/drm_modes.h> 10cc3e8a21SDmitry Baryshkov #include <drm/drm_probe_helper.h> 11cc3e8a21SDmitry Baryshkov #include <drm/bridge/imx.h> 12cc3e8a21SDmitry Baryshkov 13cc3e8a21SDmitry Baryshkov #include <video/of_display_timing.h> 14cc3e8a21SDmitry Baryshkov #include <video/of_videomode.h> 15cc3e8a21SDmitry Baryshkov 16cc3e8a21SDmitry Baryshkov struct imx_legacy_bridge { 17cc3e8a21SDmitry Baryshkov struct drm_bridge base; 18cc3e8a21SDmitry Baryshkov 19cc3e8a21SDmitry Baryshkov struct drm_display_mode mode; 20cc3e8a21SDmitry Baryshkov u32 bus_flags; 21cc3e8a21SDmitry Baryshkov }; 22cc3e8a21SDmitry Baryshkov 23cc3e8a21SDmitry Baryshkov #define to_imx_legacy_bridge(bridge) container_of(bridge, struct imx_legacy_bridge, base) 24cc3e8a21SDmitry Baryshkov 25cc3e8a21SDmitry Baryshkov static int imx_legacy_bridge_attach(struct drm_bridge *bridge, 26*98007a0dSMaxime Ripard struct drm_encoder *encoder, 27cc3e8a21SDmitry Baryshkov enum drm_bridge_attach_flags flags) 28cc3e8a21SDmitry Baryshkov { 29cc3e8a21SDmitry Baryshkov if (!(flags & DRM_BRIDGE_ATTACH_NO_CONNECTOR)) 30cc3e8a21SDmitry Baryshkov return -EINVAL; 31cc3e8a21SDmitry Baryshkov 32cc3e8a21SDmitry Baryshkov return 0; 33cc3e8a21SDmitry Baryshkov } 34cc3e8a21SDmitry Baryshkov 35cc3e8a21SDmitry Baryshkov static int imx_legacy_bridge_get_modes(struct drm_bridge *bridge, 36cc3e8a21SDmitry Baryshkov struct drm_connector *connector) 37cc3e8a21SDmitry Baryshkov { 38cc3e8a21SDmitry Baryshkov struct imx_legacy_bridge *imx_bridge = to_imx_legacy_bridge(bridge); 39cc3e8a21SDmitry Baryshkov int ret; 40cc3e8a21SDmitry Baryshkov 41cc3e8a21SDmitry Baryshkov ret = drm_connector_helper_get_modes_fixed(connector, &imx_bridge->mode); 42cc3e8a21SDmitry Baryshkov if (ret) 43cc3e8a21SDmitry Baryshkov return ret; 44cc3e8a21SDmitry Baryshkov 45cc3e8a21SDmitry Baryshkov connector->display_info.bus_flags = imx_bridge->bus_flags; 46cc3e8a21SDmitry Baryshkov 47cc3e8a21SDmitry Baryshkov return 0; 48cc3e8a21SDmitry Baryshkov } 49cc3e8a21SDmitry Baryshkov 50cc3e8a21SDmitry Baryshkov struct drm_bridge_funcs imx_legacy_bridge_funcs = { 51cc3e8a21SDmitry Baryshkov .attach = imx_legacy_bridge_attach, 52cc3e8a21SDmitry Baryshkov .get_modes = imx_legacy_bridge_get_modes, 53cc3e8a21SDmitry Baryshkov }; 54cc3e8a21SDmitry Baryshkov 55cc3e8a21SDmitry Baryshkov struct drm_bridge *devm_imx_drm_legacy_bridge(struct device *dev, 56cc3e8a21SDmitry Baryshkov struct device_node *np, 57cc3e8a21SDmitry Baryshkov int type) 58cc3e8a21SDmitry Baryshkov { 59cc3e8a21SDmitry Baryshkov struct imx_legacy_bridge *imx_bridge; 60cc3e8a21SDmitry Baryshkov int ret; 61cc3e8a21SDmitry Baryshkov 62cc3e8a21SDmitry Baryshkov imx_bridge = devm_kzalloc(dev, sizeof(*imx_bridge), GFP_KERNEL); 63cc3e8a21SDmitry Baryshkov if (!imx_bridge) 64cc3e8a21SDmitry Baryshkov return ERR_PTR(-ENOMEM); 65cc3e8a21SDmitry Baryshkov 66cc3e8a21SDmitry Baryshkov ret = of_get_drm_display_mode(np, 67cc3e8a21SDmitry Baryshkov &imx_bridge->mode, 68cc3e8a21SDmitry Baryshkov &imx_bridge->bus_flags, 69cc3e8a21SDmitry Baryshkov OF_USE_NATIVE_MODE); 70cc3e8a21SDmitry Baryshkov if (ret) 71cc3e8a21SDmitry Baryshkov return ERR_PTR(ret); 72cc3e8a21SDmitry Baryshkov 73cc3e8a21SDmitry Baryshkov imx_bridge->mode.type |= DRM_MODE_TYPE_DRIVER; 74cc3e8a21SDmitry Baryshkov 75cc3e8a21SDmitry Baryshkov imx_bridge->base.funcs = &imx_legacy_bridge_funcs; 76cc3e8a21SDmitry Baryshkov imx_bridge->base.of_node = np; 77cc3e8a21SDmitry Baryshkov imx_bridge->base.ops = DRM_BRIDGE_OP_MODES; 78cc3e8a21SDmitry Baryshkov imx_bridge->base.type = type; 79cc3e8a21SDmitry Baryshkov 80cc3e8a21SDmitry Baryshkov ret = devm_drm_bridge_add(dev, &imx_bridge->base); 81cc3e8a21SDmitry Baryshkov if (ret) 82cc3e8a21SDmitry Baryshkov return ERR_PTR(ret); 83cc3e8a21SDmitry Baryshkov 84cc3e8a21SDmitry Baryshkov return &imx_bridge->base; 85cc3e8a21SDmitry Baryshkov } 86cc3e8a21SDmitry Baryshkov EXPORT_SYMBOL_GPL(devm_imx_drm_legacy_bridge); 87cc3e8a21SDmitry Baryshkov 88cc3e8a21SDmitry Baryshkov MODULE_LICENSE("GPL"); 89df606be4SArnd Bergmann MODULE_DESCRIPTION("Freescale i.MX DRM bridge driver for legacy DT bindings"); 90