Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

drm/bridge: make bridge registration independent of drm flow

Currently, third party bridge drivers(ptn3460) are dependent
on the corresponding encoder driver init, since bridge driver
needs a drm_device pointer to finish drm initializations.
The encoder driver passes the drm_device pointer to the
bridge driver. Because of this dependency, third party drivers
like ptn3460 doesn't adhere to the driver model.

In this patch, we reframe the bridge registration framework
so that bridge initialization is split into 2 steps, and
bridge registration happens independent of drm flow:
--Step 1: gather all the bridge settings independent of drm and
add the bridge onto a global list of bridges.
--Step 2: when the encoder driver is probed, call drm_bridge_attach
for the corresponding bridge so that the bridge receives
drm_device pointer and continues with connector and other
drm initializations.

The old set of bridge helpers are removed, and a set of new helpers
are added to accomplish the 2 step initialization.

The bridge devices register themselves onto global list of bridges
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 to the bridge object.

drm_bridge_attach inturn calls "bridge->funcs->attach" so that
bridge can continue with drm related initializations.

Signed-off-by: Ajay Kumar <ajaykumar.rs@samsung.com>
Acked-by: Inki Dae <inki.dae@samsung.com>
Tested-by: Rahul Sharma <rahul.sharma@samsung.com>
Tested-by: Javier Martinez Canillas <javier.martinez@collabora.co.uk>
Tested-by: Gustavo Padovan <gustavo.padovan@collabora.co.uk>
Tested-by: Sjoerd Simons <sjoerd.simons@collabora.co.uk>
Signed-off-by: Thierry Reding <treding@nvidia.com>

authored by

Ajay Kumar and committed by
Thierry Reding
3d3f8b1f b07b90fd

+133 -119
+1 -1
drivers/gpu/drm/Makefile
··· 14 14 drm_info.o drm_debugfs.o drm_encoder_slave.o \ 15 15 drm_trace_points.o drm_global.o drm_prime.o \ 16 16 drm_rect.o drm_vma_manager.o drm_flip_work.o \ 17 - drm_modeset_lock.o drm_atomic.o 17 + drm_modeset_lock.o drm_atomic.o drm_bridge.o 18 18 19 19 drm-$(CONFIG_COMPAT) += drm_ioc32.o 20 20 drm-$(CONFIG_DRM_GEM_CMA_HELPER) += drm_gem_cma_helper.o
+13 -14
drivers/gpu/drm/bridge/ptn3460.c
··· 176 176 { 177 177 } 178 178 179 - static void ptn3460_bridge_destroy(struct drm_bridge *bridge) 180 - { 181 - struct ptn3460_bridge *ptn_bridge = bridge_to_ptn3460(bridge); 182 - 183 - drm_bridge_cleanup(bridge); 184 - if (gpio_is_valid(ptn_bridge->gpio_pd_n)) 185 - gpio_free(ptn_bridge->gpio_pd_n); 186 - if (gpio_is_valid(ptn_bridge->gpio_rst_n)) 187 - gpio_free(ptn_bridge->gpio_rst_n); 188 - /* Nothing else to free, we've got devm allocated memory */ 189 - } 190 - 191 179 static struct drm_bridge_funcs ptn3460_bridge_funcs = { 192 180 .pre_enable = ptn3460_pre_enable, 193 181 .enable = ptn3460_enable, 194 182 .disable = ptn3460_disable, 195 183 .post_disable = ptn3460_post_disable, 196 - .destroy = ptn3460_bridge_destroy, 197 184 }; 198 185 199 186 static int ptn3460_get_modes(struct drm_connector *connector) ··· 301 314 } 302 315 303 316 ptn_bridge->bridge.funcs = &ptn3460_bridge_funcs; 304 - ret = drm_bridge_init(dev, &ptn_bridge->bridge); 317 + ret = drm_bridge_attach(dev, &ptn_bridge->bridge); 305 318 if (ret) { 306 319 DRM_ERROR("Failed to initialize bridge with drm\n"); 307 320 goto err; ··· 330 343 return ret; 331 344 } 332 345 EXPORT_SYMBOL(ptn3460_init); 346 + 347 + void ptn3460_destroy(struct drm_bridge *bridge) 348 + { 349 + struct ptn3460_bridge *ptn_bridge = bridge->driver_private; 350 + 351 + if (gpio_is_valid(ptn_bridge->gpio_pd_n)) 352 + gpio_free(ptn_bridge->gpio_pd_n); 353 + if (gpio_is_valid(ptn_bridge->gpio_rst_n)) 354 + gpio_free(ptn_bridge->gpio_rst_n); 355 + /* Nothing else to free, we've got devm allocated memory */ 356 + } 357 + EXPORT_SYMBOL(ptn3460_destroy);
+91
drivers/gpu/drm/drm_bridge.c
··· 1 + /* 2 + * Copyright (c) 2014 Samsung Electronics Co., Ltd 3 + * 4 + * Permission is hereby granted, free of charge, to any person obtaining a 5 + * copy of this software and associated documentation files (the "Software"), 6 + * to deal in the Software without restriction, including without limitation 7 + * the rights to use, copy, modify, merge, publish, distribute, sub license, 8 + * and/or sell copies of the Software, and to permit persons to whom the 9 + * Software is furnished to do so, subject to the following conditions: 10 + * 11 + * The above copyright notice and this permission notice (including the 12 + * next paragraph) shall be included in all copies or substantial portions 13 + * of the Software. 14 + * 15 + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 + * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL 18 + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 20 + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 21 + * DEALINGS IN THE SOFTWARE. 22 + */ 23 + 24 + #include <linux/err.h> 25 + #include <linux/module.h> 26 + 27 + #include <drm/drm_crtc.h> 28 + 29 + #include "drm/drmP.h" 30 + 31 + static DEFINE_MUTEX(bridge_lock); 32 + static LIST_HEAD(bridge_list); 33 + 34 + int drm_bridge_add(struct drm_bridge *bridge) 35 + { 36 + mutex_lock(&bridge_lock); 37 + list_add_tail(&bridge->list, &bridge_list); 38 + mutex_unlock(&bridge_lock); 39 + 40 + return 0; 41 + } 42 + EXPORT_SYMBOL(drm_bridge_add); 43 + 44 + void drm_bridge_remove(struct drm_bridge *bridge) 45 + { 46 + mutex_lock(&bridge_lock); 47 + list_del_init(&bridge->list); 48 + mutex_unlock(&bridge_lock); 49 + } 50 + EXPORT_SYMBOL(drm_bridge_remove); 51 + 52 + extern int drm_bridge_attach(struct drm_device *dev, struct drm_bridge *bridge) 53 + { 54 + if (!dev || !bridge) 55 + return -EINVAL; 56 + 57 + if (bridge->dev) 58 + return -EBUSY; 59 + 60 + bridge->dev = dev; 61 + 62 + if (bridge->funcs->attach) 63 + return bridge->funcs->attach(bridge); 64 + 65 + return 0; 66 + } 67 + EXPORT_SYMBOL(drm_bridge_attach); 68 + 69 + #ifdef CONFIG_OF 70 + struct drm_bridge *of_drm_find_bridge(struct device_node *np) 71 + { 72 + struct drm_bridge *bridge; 73 + 74 + mutex_lock(&bridge_lock); 75 + 76 + list_for_each_entry(bridge, &bridge_list, list) { 77 + if (bridge->of_node == np) { 78 + mutex_unlock(&bridge_lock); 79 + return bridge; 80 + } 81 + } 82 + 83 + mutex_unlock(&bridge_lock); 84 + return NULL; 85 + } 86 + EXPORT_SYMBOL(of_drm_find_bridge); 87 + #endif 88 + 89 + MODULE_AUTHOR("Ajay Kumar <ajaykumar.rs@samsung.com>"); 90 + MODULE_DESCRIPTION("DRM bridge infrastructure"); 91 + MODULE_LICENSE("GPL and additional rights");
-67
drivers/gpu/drm/drm_crtc.c
··· 1066 1066 EXPORT_SYMBOL(drm_connector_unplug_all); 1067 1067 1068 1068 /** 1069 - * drm_bridge_init - initialize a drm transcoder/bridge 1070 - * @dev: drm device 1071 - * @bridge: transcoder/bridge to set up 1072 - * 1073 - * Initialises a preallocated bridge. Bridges should be 1074 - * subclassed as part of driver connector objects. 1075 - * 1076 - * Returns: 1077 - * Zero on success, error code on failure. 1078 - */ 1079 - int drm_bridge_init(struct drm_device *dev, struct drm_bridge *bridge) 1080 - { 1081 - int ret; 1082 - 1083 - drm_modeset_lock_all(dev); 1084 - 1085 - ret = drm_mode_object_get(dev, &bridge->base, DRM_MODE_OBJECT_BRIDGE); 1086 - if (ret) 1087 - goto out; 1088 - 1089 - bridge->dev = dev; 1090 - 1091 - list_add_tail(&bridge->head, &dev->mode_config.bridge_list); 1092 - dev->mode_config.num_bridge++; 1093 - 1094 - out: 1095 - drm_modeset_unlock_all(dev); 1096 - return ret; 1097 - } 1098 - EXPORT_SYMBOL(drm_bridge_init); 1099 - 1100 - /** 1101 - * drm_bridge_cleanup - cleans up an initialised bridge 1102 - * @bridge: bridge to cleanup 1103 - * 1104 - * Cleans up the bridge but doesn't free the object. 1105 - */ 1106 - void drm_bridge_cleanup(struct drm_bridge *bridge) 1107 - { 1108 - struct drm_device *dev = bridge->dev; 1109 - 1110 - drm_modeset_lock_all(dev); 1111 - drm_mode_object_put(dev, &bridge->base); 1112 - list_del(&bridge->head); 1113 - dev->mode_config.num_bridge--; 1114 - drm_modeset_unlock_all(dev); 1115 - 1116 - memset(bridge, 0, sizeof(*bridge)); 1117 - } 1118 - EXPORT_SYMBOL(drm_bridge_cleanup); 1119 - 1120 - /** 1121 1069 * drm_encoder_init - Init a preallocated encoder 1122 1070 * @dev: drm device 1123 1071 * @encoder: the encoder to init ··· 1660 1712 total_objects += dev->mode_config.num_crtc; 1661 1713 total_objects += dev->mode_config.num_connector; 1662 1714 total_objects += dev->mode_config.num_encoder; 1663 - total_objects += dev->mode_config.num_bridge; 1664 1715 1665 1716 group->id_list = kcalloc(total_objects, sizeof(uint32_t), GFP_KERNEL); 1666 1717 if (!group->id_list) ··· 1668 1721 group->num_crtcs = 0; 1669 1722 group->num_connectors = 0; 1670 1723 group->num_encoders = 0; 1671 - group->num_bridges = 0; 1672 1724 return 0; 1673 1725 } 1674 1726 ··· 1687 1741 struct drm_crtc *crtc; 1688 1742 struct drm_encoder *encoder; 1689 1743 struct drm_connector *connector; 1690 - struct drm_bridge *bridge; 1691 1744 int ret; 1692 1745 1693 1746 ret = drm_mode_group_init(dev, group); ··· 1703 1758 list_for_each_entry(connector, &dev->mode_config.connector_list, head) 1704 1759 group->id_list[group->num_crtcs + group->num_encoders + 1705 1760 group->num_connectors++] = connector->base.id; 1706 - 1707 - list_for_each_entry(bridge, &dev->mode_config.bridge_list, head) 1708 - group->id_list[group->num_crtcs + group->num_encoders + 1709 - group->num_connectors + group->num_bridges++] = 1710 - bridge->base.id; 1711 1761 1712 1762 return 0; 1713 1763 } ··· 5380 5440 INIT_LIST_HEAD(&dev->mode_config.fb_list); 5381 5441 INIT_LIST_HEAD(&dev->mode_config.crtc_list); 5382 5442 INIT_LIST_HEAD(&dev->mode_config.connector_list); 5383 - INIT_LIST_HEAD(&dev->mode_config.bridge_list); 5384 5443 INIT_LIST_HEAD(&dev->mode_config.encoder_list); 5385 5444 INIT_LIST_HEAD(&dev->mode_config.property_list); 5386 5445 INIT_LIST_HEAD(&dev->mode_config.property_blob_list); ··· 5419 5480 struct drm_connector *connector, *ot; 5420 5481 struct drm_crtc *crtc, *ct; 5421 5482 struct drm_encoder *encoder, *enct; 5422 - struct drm_bridge *bridge, *brt; 5423 5483 struct drm_framebuffer *fb, *fbt; 5424 5484 struct drm_property *property, *pt; 5425 5485 struct drm_property_blob *blob, *bt; ··· 5427 5489 list_for_each_entry_safe(encoder, enct, &dev->mode_config.encoder_list, 5428 5490 head) { 5429 5491 encoder->funcs->destroy(encoder); 5430 - } 5431 - 5432 - list_for_each_entry_safe(bridge, brt, 5433 - &dev->mode_config.bridge_list, head) { 5434 - bridge->funcs->destroy(bridge); 5435 5492 } 5436 5493 5437 5494 list_for_each_entry_safe(connector, ot,
+2 -2
drivers/gpu/drm/msm/hdmi/hdmi.c
··· 247 247 return 0; 248 248 249 249 fail: 250 - /* bridge/connector are normally destroyed by drm: */ 250 + /* bridge is normally destroyed by drm: */ 251 251 if (hdmi->bridge) { 252 - hdmi->bridge->funcs->destroy(hdmi->bridge); 252 + hdmi_bridge_destroy(hdmi->bridge); 253 253 hdmi->bridge = NULL; 254 254 } 255 255 if (hdmi->connector) {
+1
drivers/gpu/drm/msm/hdmi/hdmi.h
··· 146 146 */ 147 147 148 148 struct drm_bridge *hdmi_bridge_init(struct hdmi *hdmi); 149 + void hdmi_bridge_destroy(struct drm_bridge *bridge); 149 150 150 151 /* 151 152 * hdmi connector:
+2 -4
drivers/gpu/drm/msm/hdmi/hdmi_bridge.c
··· 23 23 }; 24 24 #define to_hdmi_bridge(x) container_of(x, struct hdmi_bridge, base) 25 25 26 - static void hdmi_bridge_destroy(struct drm_bridge *bridge) 26 + void hdmi_bridge_destroy(struct drm_bridge *bridge) 27 27 { 28 28 struct hdmi_bridge *hdmi_bridge = to_hdmi_bridge(bridge); 29 - drm_bridge_cleanup(bridge); 30 29 kfree(hdmi_bridge); 31 30 } 32 31 ··· 199 200 .disable = hdmi_bridge_disable, 200 201 .post_disable = hdmi_bridge_post_disable, 201 202 .mode_set = hdmi_bridge_mode_set, 202 - .destroy = hdmi_bridge_destroy, 203 203 }; 204 204 205 205 ··· 220 222 bridge = &hdmi_bridge->base; 221 223 bridge->funcs = &hdmi_bridge_funcs; 222 224 223 - drm_bridge_init(hdmi->dev, bridge); 225 + drm_bridge_attach(hdmi->dev, bridge); 224 226 225 227 return bridge; 226 228
+1 -9
drivers/gpu/drm/sti/sti_hda.c
··· 508 508 /* do nothing */ 509 509 } 510 510 511 - static void sti_hda_brigde_destroy(struct drm_bridge *bridge) 512 - { 513 - drm_bridge_cleanup(bridge); 514 - kfree(bridge); 515 - } 516 - 517 511 static const struct drm_bridge_funcs sti_hda_bridge_funcs = { 518 512 .pre_enable = sti_hda_pre_enable, 519 513 .enable = sti_hda_bridge_nope, 520 514 .disable = sti_hda_disable, 521 515 .post_disable = sti_hda_bridge_nope, 522 516 .mode_set = sti_hda_set_mode, 523 - .destroy = sti_hda_brigde_destroy, 524 517 }; 525 518 526 519 static int sti_hda_connector_get_modes(struct drm_connector *connector) ··· 658 665 659 666 bridge->driver_private = hda; 660 667 bridge->funcs = &sti_hda_bridge_funcs; 661 - drm_bridge_init(drm_dev, bridge); 668 + drm_bridge_attach(drm_dev, bridge); 662 669 663 670 encoder->bridge = bridge; 664 671 connector->encoder = encoder; ··· 687 694 err_sysfs: 688 695 drm_connector_unregister(drm_connector); 689 696 err_connector: 690 - drm_bridge_cleanup(bridge); 691 697 drm_connector_cleanup(drm_connector); 692 698 return -EINVAL; 693 699 }
+1 -9
drivers/gpu/drm/sti/sti_hdmi.c
··· 463 463 /* do nothing */ 464 464 } 465 465 466 - static void sti_hdmi_brigde_destroy(struct drm_bridge *bridge) 467 - { 468 - drm_bridge_cleanup(bridge); 469 - kfree(bridge); 470 - } 471 - 472 466 static const struct drm_bridge_funcs sti_hdmi_bridge_funcs = { 473 467 .pre_enable = sti_hdmi_pre_enable, 474 468 .enable = sti_hdmi_bridge_nope, 475 469 .disable = sti_hdmi_disable, 476 470 .post_disable = sti_hdmi_bridge_nope, 477 471 .mode_set = sti_hdmi_set_mode, 478 - .destroy = sti_hdmi_brigde_destroy, 479 472 }; 480 473 481 474 static int sti_hdmi_connector_get_modes(struct drm_connector *connector) ··· 629 636 630 637 bridge->driver_private = hdmi; 631 638 bridge->funcs = &sti_hdmi_bridge_funcs; 632 - drm_bridge_init(drm_dev, bridge); 639 + drm_bridge_attach(drm_dev, bridge); 633 640 634 641 encoder->bridge = bridge; 635 642 connector->encoder = encoder; ··· 661 668 err_sysfs: 662 669 drm_connector_unregister(drm_connector); 663 670 err_connector: 664 - drm_bridge_cleanup(bridge); 665 671 drm_connector_cleanup(drm_connector); 666 672 err_adapt: 667 673 put_device(&hdmi->ddc_adapt->dev);
+8
include/drm/bridge/ptn3460.h
··· 15 15 #define _DRM_BRIDGE_PTN3460_H_ 16 16 17 17 struct drm_device; 18 + struct drm_bridge; 18 19 struct drm_encoder; 19 20 struct i2c_client; 20 21 struct device_node; ··· 24 23 25 24 int ptn3460_init(struct drm_device *dev, struct drm_encoder *encoder, 26 25 struct i2c_client *client, struct device_node *node); 26 + 27 + void ptn3460_destroy(struct drm_bridge *bridge); 28 + 27 29 #else 28 30 29 31 static inline int ptn3460_init(struct drm_device *dev, ··· 34 30 struct device_node *node) 35 31 { 36 32 return 0; 33 + } 34 + 35 + static inline void ptn3460_destroy(struct drm_bridge *bridge) 36 + { 37 37 } 38 38 39 39 #endif
+13 -13
include/drm/drm_crtc.h
··· 868 868 869 869 /** 870 870 * struct drm_bridge_funcs - drm_bridge control functions 871 + * @attach: Called during drm_bridge_attach 871 872 * @mode_fixup: Try to fixup (or reject entirely) proposed mode for this bridge 872 873 * @disable: Called right before encoder prepare, disables the bridge 873 874 * @post_disable: Called right after encoder prepare, for lockstepped disable 874 875 * @mode_set: Set this mode to the bridge 875 876 * @pre_enable: Called right before encoder commit, for lockstepped commit 876 877 * @enable: Called right after encoder commit, enables the bridge 877 - * @destroy: make object go away 878 878 */ 879 879 struct drm_bridge_funcs { 880 + int (*attach)(struct drm_bridge *bridge); 880 881 bool (*mode_fixup)(struct drm_bridge *bridge, 881 882 const struct drm_display_mode *mode, 882 883 struct drm_display_mode *adjusted_mode); ··· 888 887 struct drm_display_mode *adjusted_mode); 889 888 void (*pre_enable)(struct drm_bridge *bridge); 890 889 void (*enable)(struct drm_bridge *bridge); 891 - void (*destroy)(struct drm_bridge *bridge); 892 890 }; 893 891 894 892 /** 895 893 * struct drm_bridge - central DRM bridge control structure 896 894 * @dev: DRM device this bridge belongs to 897 - * @head: list management 895 + * @of_node: device node pointer to the bridge 896 + * @list: to keep track of all added bridges 898 897 * @base: base mode object 899 898 * @funcs: control functions 900 899 * @driver_private: pointer to the bridge driver's internal context 901 900 */ 902 901 struct drm_bridge { 903 902 struct drm_device *dev; 904 - struct list_head head; 905 - 906 - struct drm_mode_object base; 903 + struct drm_encoder *encoder; 904 + #ifdef CONFIG_OF 905 + struct device_node *of_node; 906 + #endif 907 + struct list_head list; 907 908 908 909 const struct drm_bridge_funcs *funcs; 909 910 void *driver_private; ··· 1010 1007 uint32_t num_crtcs; 1011 1008 uint32_t num_encoders; 1012 1009 uint32_t num_connectors; 1013 - uint32_t num_bridges; 1014 1010 1015 1011 /* list of object IDs for this group */ 1016 1012 uint32_t *id_list; ··· 1028 1026 * @fb_list: list of framebuffers available 1029 1027 * @num_connector: number of connectors on this device 1030 1028 * @connector_list: list of connector objects 1031 - * @num_bridge: number of bridges on this device 1032 - * @bridge_list: list of bridge objects 1033 1029 * @num_encoder: number of encoders on this device 1034 1030 * @encoder_list: list of encoder objects 1035 1031 * @num_overlay_plane: number of overlay planes on this device ··· 1072 1072 1073 1073 int num_connector; 1074 1074 struct list_head connector_list; 1075 - int num_bridge; 1076 - struct list_head bridge_list; 1077 1075 int num_encoder; 1078 1076 struct list_head encoder_list; 1079 1077 ··· 1220 1222 /* helper to unplug all connectors from sysfs for device */ 1221 1223 extern void drm_connector_unplug_all(struct drm_device *dev); 1222 1224 1223 - extern int drm_bridge_init(struct drm_device *dev, struct drm_bridge *bridge); 1224 - extern void drm_bridge_cleanup(struct drm_bridge *bridge); 1225 + extern int drm_bridge_add(struct drm_bridge *bridge); 1226 + extern void drm_bridge_remove(struct drm_bridge *bridge); 1227 + extern struct drm_bridge *of_drm_find_bridge(struct device_node *np); 1228 + extern int drm_bridge_attach(struct drm_device *dev, struct drm_bridge *bridge); 1225 1229 1226 1230 extern int drm_encoder_init(struct drm_device *dev, 1227 1231 struct drm_encoder *encoder,