1*ba2db93cSDamon Ding // SPDX-License-Identifier: GPL-2.0+ 2*ba2db93cSDamon Ding /* 3*ba2db93cSDamon Ding * Copyright (C) 2012 Sascha Hauer, Pengutronix 4*ba2db93cSDamon Ding * 5*ba2db93cSDamon Ding * bridge driver for legacy DT bindings, utilizing display-timings node 6*ba2db93cSDamon Ding * 7*ba2db93cSDamon Ding * Author: Dmitry Baryshkov <dmitry.baryshkov@oss.qualcomm.com> 8*ba2db93cSDamon Ding */ 9*ba2db93cSDamon Ding 10*ba2db93cSDamon Ding #include <linux/export.h> 11*ba2db93cSDamon Ding 12*ba2db93cSDamon Ding #include <drm/drm_bridge.h> 13*ba2db93cSDamon Ding #include <drm/drm_modes.h> 14*ba2db93cSDamon Ding #include <drm/drm_probe_helper.h> 15*ba2db93cSDamon Ding #include <drm/bridge/of-display-mode-bridge.h> 16*ba2db93cSDamon Ding 17*ba2db93cSDamon Ding #include <video/of_display_timing.h> 18*ba2db93cSDamon Ding #include <video/of_videomode.h> 19*ba2db93cSDamon Ding 20*ba2db93cSDamon Ding struct of_display_mode_bridge { 21*ba2db93cSDamon Ding struct drm_bridge base; 22*ba2db93cSDamon Ding 23*ba2db93cSDamon Ding struct drm_display_mode mode; 24*ba2db93cSDamon Ding u32 bus_flags; 25*ba2db93cSDamon Ding }; 26*ba2db93cSDamon Ding 27*ba2db93cSDamon Ding #define to_of_display_mode_bridge(bridge) container_of(bridge, struct of_display_mode_bridge, base) 28*ba2db93cSDamon Ding 29*ba2db93cSDamon Ding static int of_display_mode_bridge_attach(struct drm_bridge *bridge, 30*ba2db93cSDamon Ding struct drm_encoder *encoder, 31*ba2db93cSDamon Ding enum drm_bridge_attach_flags flags) 32*ba2db93cSDamon Ding { 33*ba2db93cSDamon Ding if (!(flags & DRM_BRIDGE_ATTACH_NO_CONNECTOR)) 34*ba2db93cSDamon Ding return -EINVAL; 35*ba2db93cSDamon Ding 36*ba2db93cSDamon Ding return 0; 37*ba2db93cSDamon Ding } 38*ba2db93cSDamon Ding 39*ba2db93cSDamon Ding static int of_display_mode_bridge_get_modes(struct drm_bridge *bridge, 40*ba2db93cSDamon Ding struct drm_connector *connector) 41*ba2db93cSDamon Ding { 42*ba2db93cSDamon Ding struct of_display_mode_bridge *of_bridge = to_of_display_mode_bridge(bridge); 43*ba2db93cSDamon Ding int ret; 44*ba2db93cSDamon Ding 45*ba2db93cSDamon Ding ret = drm_connector_helper_get_modes_fixed(connector, &of_bridge->mode); 46*ba2db93cSDamon Ding if (ret) 47*ba2db93cSDamon Ding return ret; 48*ba2db93cSDamon Ding 49*ba2db93cSDamon Ding connector->display_info.bus_flags = of_bridge->bus_flags; 50*ba2db93cSDamon Ding 51*ba2db93cSDamon Ding return 0; 52*ba2db93cSDamon Ding } 53*ba2db93cSDamon Ding 54*ba2db93cSDamon Ding struct drm_bridge_funcs of_display_mode_bridge_funcs = { 55*ba2db93cSDamon Ding .attach = of_display_mode_bridge_attach, 56*ba2db93cSDamon Ding .get_modes = of_display_mode_bridge_get_modes, 57*ba2db93cSDamon Ding }; 58*ba2db93cSDamon Ding 59*ba2db93cSDamon Ding struct drm_bridge *devm_drm_of_display_mode_bridge(struct device *dev, 60*ba2db93cSDamon Ding struct device_node *np, 61*ba2db93cSDamon Ding int type) 62*ba2db93cSDamon Ding { 63*ba2db93cSDamon Ding struct of_display_mode_bridge *of_bridge; 64*ba2db93cSDamon Ding int ret; 65*ba2db93cSDamon Ding 66*ba2db93cSDamon Ding of_bridge = devm_drm_bridge_alloc(dev, struct of_display_mode_bridge, 67*ba2db93cSDamon Ding base, &of_display_mode_bridge_funcs); 68*ba2db93cSDamon Ding if (IS_ERR(of_bridge)) 69*ba2db93cSDamon Ding return ERR_CAST(of_bridge); 70*ba2db93cSDamon Ding 71*ba2db93cSDamon Ding ret = of_get_drm_display_mode(np, 72*ba2db93cSDamon Ding &of_bridge->mode, 73*ba2db93cSDamon Ding &of_bridge->bus_flags, 74*ba2db93cSDamon Ding OF_USE_NATIVE_MODE); 75*ba2db93cSDamon Ding if (ret) 76*ba2db93cSDamon Ding return ERR_PTR(ret); 77*ba2db93cSDamon Ding 78*ba2db93cSDamon Ding of_bridge->mode.type |= DRM_MODE_TYPE_DRIVER; 79*ba2db93cSDamon Ding 80*ba2db93cSDamon Ding of_bridge->base.of_node = np; 81*ba2db93cSDamon Ding of_bridge->base.ops = DRM_BRIDGE_OP_MODES; 82*ba2db93cSDamon Ding of_bridge->base.type = type; 83*ba2db93cSDamon Ding 84*ba2db93cSDamon Ding ret = devm_drm_bridge_add(dev, &of_bridge->base); 85*ba2db93cSDamon Ding if (ret) 86*ba2db93cSDamon Ding return ERR_PTR(ret); 87*ba2db93cSDamon Ding 88*ba2db93cSDamon Ding return &of_bridge->base; 89*ba2db93cSDamon Ding } 90*ba2db93cSDamon Ding EXPORT_SYMBOL_GPL(devm_drm_of_display_mode_bridge); 91*ba2db93cSDamon Ding 92*ba2db93cSDamon Ding MODULE_LICENSE("GPL"); 93*ba2db93cSDamon Ding MODULE_DESCRIPTION("DRM bridge driver for legacy DT bindings"); 94