Skip to content

Commit 3d3f8b1

Browse files
AjayKumarRSthierryreding
authored andcommitted
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 <[email protected]> Acked-by: Inki Dae <[email protected]> Tested-by: Rahul Sharma <[email protected]> Tested-by: Javier Martinez Canillas <[email protected]> Tested-by: Gustavo Padovan <[email protected]> Tested-by: Sjoerd Simons <[email protected]> Signed-off-by: Thierry Reding <[email protected]>
1 parent b07b90f commit 3d3f8b1

File tree

11 files changed

+133
-119
lines changed

11 files changed

+133
-119
lines changed

drivers/gpu/drm/Makefile

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ drm-y := drm_auth.o drm_bufs.o drm_cache.o \
1414
drm_info.o drm_debugfs.o drm_encoder_slave.o \
1515
drm_trace_points.o drm_global.o drm_prime.o \
1616
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
1818

1919
drm-$(CONFIG_COMPAT) += drm_ioc32.o
2020
drm-$(CONFIG_DRM_GEM_CMA_HELPER) += drm_gem_cma_helper.o

drivers/gpu/drm/bridge/ptn3460.c

Lines changed: 13 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -176,24 +176,11 @@ static void ptn3460_post_disable(struct drm_bridge *bridge)
176176
{
177177
}
178178

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-
191179
static struct drm_bridge_funcs ptn3460_bridge_funcs = {
192180
.pre_enable = ptn3460_pre_enable,
193181
.enable = ptn3460_enable,
194182
.disable = ptn3460_disable,
195183
.post_disable = ptn3460_post_disable,
196-
.destroy = ptn3460_bridge_destroy,
197184
};
198185

199186
static int ptn3460_get_modes(struct drm_connector *connector)
@@ -314,7 +301,7 @@ int ptn3460_init(struct drm_device *dev, struct drm_encoder *encoder,
314301
}
315302

316303
ptn_bridge->bridge.funcs = &ptn3460_bridge_funcs;
317-
ret = drm_bridge_init(dev, &ptn_bridge->bridge);
304+
ret = drm_bridge_attach(dev, &ptn_bridge->bridge);
318305
if (ret) {
319306
DRM_ERROR("Failed to initialize bridge with drm\n");
320307
goto err;
@@ -343,3 +330,15 @@ int ptn3460_init(struct drm_device *dev, struct drm_encoder *encoder,
343330
return ret;
344331
}
345332
EXPORT_SYMBOL(ptn3460_init);
333+
334+
void ptn3460_destroy(struct drm_bridge *bridge)
335+
{
336+
struct ptn3460_bridge *ptn_bridge = bridge->driver_private;
337+
338+
if (gpio_is_valid(ptn_bridge->gpio_pd_n))
339+
gpio_free(ptn_bridge->gpio_pd_n);
340+
if (gpio_is_valid(ptn_bridge->gpio_rst_n))
341+
gpio_free(ptn_bridge->gpio_rst_n);
342+
/* Nothing else to free, we've got devm allocated memory */
343+
}
344+
EXPORT_SYMBOL(ptn3460_destroy);

drivers/gpu/drm/drm_bridge.c

Lines changed: 91 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,91 @@
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 <[email protected]>");
90+
MODULE_DESCRIPTION("DRM bridge infrastructure");
91+
MODULE_LICENSE("GPL and additional rights");

drivers/gpu/drm/drm_crtc.c

Lines changed: 0 additions & 67 deletions
Original file line numberDiff line numberDiff line change
@@ -1065,58 +1065,6 @@ void drm_connector_unplug_all(struct drm_device *dev)
10651065
}
10661066
EXPORT_SYMBOL(drm_connector_unplug_all);
10671067

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-
11201068
/**
11211069
* drm_encoder_init - Init a preallocated encoder
11221070
* @dev: drm device
@@ -1712,7 +1660,6 @@ static int drm_mode_group_init(struct drm_device *dev, struct drm_mode_group *gr
17121660
total_objects += dev->mode_config.num_crtc;
17131661
total_objects += dev->mode_config.num_connector;
17141662
total_objects += dev->mode_config.num_encoder;
1715-
total_objects += dev->mode_config.num_bridge;
17161663

17171664
group->id_list = kcalloc(total_objects, sizeof(uint32_t), GFP_KERNEL);
17181665
if (!group->id_list)
@@ -1721,7 +1668,6 @@ static int drm_mode_group_init(struct drm_device *dev, struct drm_mode_group *gr
17211668
group->num_crtcs = 0;
17221669
group->num_connectors = 0;
17231670
group->num_encoders = 0;
1724-
group->num_bridges = 0;
17251671
return 0;
17261672
}
17271673

@@ -1741,7 +1687,6 @@ int drm_mode_group_init_legacy_group(struct drm_device *dev,
17411687
struct drm_crtc *crtc;
17421688
struct drm_encoder *encoder;
17431689
struct drm_connector *connector;
1744-
struct drm_bridge *bridge;
17451690
int ret;
17461691

17471692
ret = drm_mode_group_init(dev, group);
@@ -1759,11 +1704,6 @@ int drm_mode_group_init_legacy_group(struct drm_device *dev,
17591704
group->id_list[group->num_crtcs + group->num_encoders +
17601705
group->num_connectors++] = connector->base.id;
17611706

1762-
list_for_each_entry(bridge, &dev->mode_config.bridge_list, head)
1763-
group->id_list[group->num_crtcs + group->num_encoders +
1764-
group->num_connectors + group->num_bridges++] =
1765-
bridge->base.id;
1766-
17671707
return 0;
17681708
}
17691709
EXPORT_SYMBOL(drm_mode_group_init_legacy_group);
@@ -5440,7 +5380,6 @@ void drm_mode_config_init(struct drm_device *dev)
54405380
INIT_LIST_HEAD(&dev->mode_config.fb_list);
54415381
INIT_LIST_HEAD(&dev->mode_config.crtc_list);
54425382
INIT_LIST_HEAD(&dev->mode_config.connector_list);
5443-
INIT_LIST_HEAD(&dev->mode_config.bridge_list);
54445383
INIT_LIST_HEAD(&dev->mode_config.encoder_list);
54455384
INIT_LIST_HEAD(&dev->mode_config.property_list);
54465385
INIT_LIST_HEAD(&dev->mode_config.property_blob_list);
@@ -5480,7 +5419,6 @@ void drm_mode_config_cleanup(struct drm_device *dev)
54805419
struct drm_connector *connector, *ot;
54815420
struct drm_crtc *crtc, *ct;
54825421
struct drm_encoder *encoder, *enct;
5483-
struct drm_bridge *bridge, *brt;
54845422
struct drm_framebuffer *fb, *fbt;
54855423
struct drm_property *property, *pt;
54865424
struct drm_property_blob *blob, *bt;
@@ -5491,11 +5429,6 @@ void drm_mode_config_cleanup(struct drm_device *dev)
54915429
encoder->funcs->destroy(encoder);
54925430
}
54935431

5494-
list_for_each_entry_safe(bridge, brt,
5495-
&dev->mode_config.bridge_list, head) {
5496-
bridge->funcs->destroy(bridge);
5497-
}
5498-
54995432
list_for_each_entry_safe(connector, ot,
55005433
&dev->mode_config.connector_list, head) {
55015434
connector->funcs->destroy(connector);

drivers/gpu/drm/msm/hdmi/hdmi.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -247,9 +247,9 @@ int hdmi_modeset_init(struct hdmi *hdmi,
247247
return 0;
248248

249249
fail:
250-
/* bridge/connector are normally destroyed by drm: */
250+
/* bridge is normally destroyed by drm: */
251251
if (hdmi->bridge) {
252-
hdmi->bridge->funcs->destroy(hdmi->bridge);
252+
hdmi_bridge_destroy(hdmi->bridge);
253253
hdmi->bridge = NULL;
254254
}
255255
if (hdmi->connector) {

drivers/gpu/drm/msm/hdmi/hdmi.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -146,6 +146,7 @@ void hdmi_audio_set_sample_rate(struct hdmi *hdmi, int rate);
146146
*/
147147

148148
struct drm_bridge *hdmi_bridge_init(struct hdmi *hdmi);
149+
void hdmi_bridge_destroy(struct drm_bridge *bridge);
149150

150151
/*
151152
* hdmi connector:

drivers/gpu/drm/msm/hdmi/hdmi_bridge.c

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -23,10 +23,9 @@ struct hdmi_bridge {
2323
};
2424
#define to_hdmi_bridge(x) container_of(x, struct hdmi_bridge, base)
2525

26-
static void hdmi_bridge_destroy(struct drm_bridge *bridge)
26+
void hdmi_bridge_destroy(struct drm_bridge *bridge)
2727
{
2828
struct hdmi_bridge *hdmi_bridge = to_hdmi_bridge(bridge);
29-
drm_bridge_cleanup(bridge);
3029
kfree(hdmi_bridge);
3130
}
3231

@@ -200,7 +199,6 @@ static const struct drm_bridge_funcs hdmi_bridge_funcs = {
200199
.disable = hdmi_bridge_disable,
201200
.post_disable = hdmi_bridge_post_disable,
202201
.mode_set = hdmi_bridge_mode_set,
203-
.destroy = hdmi_bridge_destroy,
204202
};
205203

206204

@@ -222,7 +220,7 @@ struct drm_bridge *hdmi_bridge_init(struct hdmi *hdmi)
222220
bridge = &hdmi_bridge->base;
223221
bridge->funcs = &hdmi_bridge_funcs;
224222

225-
drm_bridge_init(hdmi->dev, bridge);
223+
drm_bridge_attach(hdmi->dev, bridge);
226224

227225
return bridge;
228226

drivers/gpu/drm/sti/sti_hda.c

Lines changed: 1 addition & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -508,19 +508,12 @@ static void sti_hda_bridge_nope(struct drm_bridge *bridge)
508508
/* do nothing */
509509
}
510510

511-
static void sti_hda_brigde_destroy(struct drm_bridge *bridge)
512-
{
513-
drm_bridge_cleanup(bridge);
514-
kfree(bridge);
515-
}
516-
517511
static const struct drm_bridge_funcs sti_hda_bridge_funcs = {
518512
.pre_enable = sti_hda_pre_enable,
519513
.enable = sti_hda_bridge_nope,
520514
.disable = sti_hda_disable,
521515
.post_disable = sti_hda_bridge_nope,
522516
.mode_set = sti_hda_set_mode,
523-
.destroy = sti_hda_brigde_destroy,
524517
};
525518

526519
static int sti_hda_connector_get_modes(struct drm_connector *connector)
@@ -665,7 +658,7 @@ static int sti_hda_bind(struct device *dev, struct device *master, void *data)
665658

666659
bridge->driver_private = hda;
667660
bridge->funcs = &sti_hda_bridge_funcs;
668-
drm_bridge_init(drm_dev, bridge);
661+
drm_bridge_attach(drm_dev, bridge);
669662

670663
encoder->bridge = bridge;
671664
connector->encoder = encoder;
@@ -694,7 +687,6 @@ static int sti_hda_bind(struct device *dev, struct device *master, void *data)
694687
err_sysfs:
695688
drm_connector_unregister(drm_connector);
696689
err_connector:
697-
drm_bridge_cleanup(bridge);
698690
drm_connector_cleanup(drm_connector);
699691
return -EINVAL;
700692
}

drivers/gpu/drm/sti/sti_hdmi.c

Lines changed: 1 addition & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -463,19 +463,12 @@ static void sti_hdmi_bridge_nope(struct drm_bridge *bridge)
463463
/* do nothing */
464464
}
465465

466-
static void sti_hdmi_brigde_destroy(struct drm_bridge *bridge)
467-
{
468-
drm_bridge_cleanup(bridge);
469-
kfree(bridge);
470-
}
471-
472466
static const struct drm_bridge_funcs sti_hdmi_bridge_funcs = {
473467
.pre_enable = sti_hdmi_pre_enable,
474468
.enable = sti_hdmi_bridge_nope,
475469
.disable = sti_hdmi_disable,
476470
.post_disable = sti_hdmi_bridge_nope,
477471
.mode_set = sti_hdmi_set_mode,
478-
.destroy = sti_hdmi_brigde_destroy,
479472
};
480473

481474
static int sti_hdmi_connector_get_modes(struct drm_connector *connector)
@@ -636,7 +629,7 @@ static int sti_hdmi_bind(struct device *dev, struct device *master, void *data)
636629

637630
bridge->driver_private = hdmi;
638631
bridge->funcs = &sti_hdmi_bridge_funcs;
639-
drm_bridge_init(drm_dev, bridge);
632+
drm_bridge_attach(drm_dev, bridge);
640633

641634
encoder->bridge = bridge;
642635
connector->encoder = encoder;
@@ -668,7 +661,6 @@ static int sti_hdmi_bind(struct device *dev, struct device *master, void *data)
668661
err_sysfs:
669662
drm_connector_unregister(drm_connector);
670663
err_connector:
671-
drm_bridge_cleanup(bridge);
672664
drm_connector_cleanup(drm_connector);
673665
err_adapt:
674666
put_device(&hdmi->ddc_adapt->dev);

0 commit comments

Comments
 (0)