Skip to content

Commit 3b336ec

Browse files
atseanpaulairlied
authored andcommitted
drm: Add drm_bridge
This patch adds the notion of a drm_bridge. A bridge is a chained device which hangs off an encoder. The drm driver using the bridge should provide the association between encoder and bridge. Once a bridge is associated with an encoder, it will participate in mode set, and dpms (via the enable/disable hooks). Signed-off-by: Sean Paul <[email protected]> Acked-by: Daniel Vetter <[email protected]> Reviewed-by: Rob Clark <[email protected]> Signed-off-by: Dave Airlie <[email protected]>
1 parent 2254f63 commit 3b336ec

File tree

3 files changed

+175
-19
lines changed

3 files changed

+175
-19
lines changed

drivers/gpu/drm/drm_crtc.c

Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -799,6 +799,41 @@ void drm_connector_unplug_all(struct drm_device *dev)
799799
}
800800
EXPORT_SYMBOL(drm_connector_unplug_all);
801801

802+
int drm_bridge_init(struct drm_device *dev, struct drm_bridge *bridge,
803+
const struct drm_bridge_funcs *funcs)
804+
{
805+
int ret;
806+
807+
drm_modeset_lock_all(dev);
808+
809+
ret = drm_mode_object_get(dev, &bridge->base, DRM_MODE_OBJECT_BRIDGE);
810+
if (ret)
811+
goto out;
812+
813+
bridge->dev = dev;
814+
bridge->funcs = funcs;
815+
816+
list_add_tail(&bridge->head, &dev->mode_config.bridge_list);
817+
dev->mode_config.num_bridge++;
818+
819+
out:
820+
drm_modeset_unlock_all(dev);
821+
return ret;
822+
}
823+
EXPORT_SYMBOL(drm_bridge_init);
824+
825+
void drm_bridge_cleanup(struct drm_bridge *bridge)
826+
{
827+
struct drm_device *dev = bridge->dev;
828+
829+
drm_modeset_lock_all(dev);
830+
drm_mode_object_put(dev, &bridge->base);
831+
list_del(&bridge->head);
832+
dev->mode_config.num_bridge--;
833+
drm_modeset_unlock_all(dev);
834+
}
835+
EXPORT_SYMBOL(drm_bridge_cleanup);
836+
802837
int drm_encoder_init(struct drm_device *dev,
803838
struct drm_encoder *encoder,
804839
const struct drm_encoder_funcs *funcs,
@@ -1184,6 +1219,7 @@ static int drm_mode_group_init(struct drm_device *dev, struct drm_mode_group *gr
11841219
total_objects += dev->mode_config.num_crtc;
11851220
total_objects += dev->mode_config.num_connector;
11861221
total_objects += dev->mode_config.num_encoder;
1222+
total_objects += dev->mode_config.num_bridge;
11871223

11881224
group->id_list = kzalloc(total_objects * sizeof(uint32_t), GFP_KERNEL);
11891225
if (!group->id_list)
@@ -1192,6 +1228,7 @@ static int drm_mode_group_init(struct drm_device *dev, struct drm_mode_group *gr
11921228
group->num_crtcs = 0;
11931229
group->num_connectors = 0;
11941230
group->num_encoders = 0;
1231+
group->num_bridges = 0;
11951232
return 0;
11961233
}
11971234

@@ -1201,6 +1238,7 @@ int drm_mode_group_init_legacy_group(struct drm_device *dev,
12011238
struct drm_crtc *crtc;
12021239
struct drm_encoder *encoder;
12031240
struct drm_connector *connector;
1241+
struct drm_bridge *bridge;
12041242
int ret;
12051243

12061244
if ((ret = drm_mode_group_init(dev, group)))
@@ -1217,6 +1255,11 @@ int drm_mode_group_init_legacy_group(struct drm_device *dev,
12171255
group->id_list[group->num_crtcs + group->num_encoders +
12181256
group->num_connectors++] = connector->base.id;
12191257

1258+
list_for_each_entry(bridge, &dev->mode_config.bridge_list, head)
1259+
group->id_list[group->num_crtcs + group->num_encoders +
1260+
group->num_connectors + group->num_bridges++] =
1261+
bridge->base.id;
1262+
12201263
return 0;
12211264
}
12221265
EXPORT_SYMBOL(drm_mode_group_init_legacy_group);
@@ -3902,6 +3945,7 @@ void drm_mode_config_init(struct drm_device *dev)
39023945
INIT_LIST_HEAD(&dev->mode_config.fb_list);
39033946
INIT_LIST_HEAD(&dev->mode_config.crtc_list);
39043947
INIT_LIST_HEAD(&dev->mode_config.connector_list);
3948+
INIT_LIST_HEAD(&dev->mode_config.bridge_list);
39053949
INIT_LIST_HEAD(&dev->mode_config.encoder_list);
39063950
INIT_LIST_HEAD(&dev->mode_config.property_list);
39073951
INIT_LIST_HEAD(&dev->mode_config.property_blob_list);
@@ -3938,6 +3982,7 @@ void drm_mode_config_cleanup(struct drm_device *dev)
39383982
struct drm_connector *connector, *ot;
39393983
struct drm_crtc *crtc, *ct;
39403984
struct drm_encoder *encoder, *enct;
3985+
struct drm_bridge *bridge, *brt;
39413986
struct drm_framebuffer *fb, *fbt;
39423987
struct drm_property *property, *pt;
39433988
struct drm_property_blob *blob, *bt;
@@ -3948,6 +3993,11 @@ void drm_mode_config_cleanup(struct drm_device *dev)
39483993
encoder->funcs->destroy(encoder);
39493994
}
39503995

3996+
list_for_each_entry_safe(bridge, brt,
3997+
&dev->mode_config.bridge_list, head) {
3998+
bridge->funcs->destroy(bridge);
3999+
}
4000+
39514001
list_for_each_entry_safe(connector, ot,
39524002
&dev->mode_config.connector_list, head) {
39534003
connector->funcs->destroy(connector);

drivers/gpu/drm/drm_crtc_helper.c

Lines changed: 70 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -257,10 +257,16 @@ drm_encoder_disable(struct drm_encoder *encoder)
257257
{
258258
struct drm_encoder_helper_funcs *encoder_funcs = encoder->helper_private;
259259

260+
if (encoder->bridge)
261+
encoder->bridge->funcs->disable(encoder->bridge);
262+
260263
if (encoder_funcs->disable)
261264
(*encoder_funcs->disable)(encoder);
262265
else
263266
(*encoder_funcs->dpms)(encoder, DRM_MODE_DPMS_OFF);
267+
268+
if (encoder->bridge)
269+
encoder->bridge->funcs->post_disable(encoder->bridge);
264270
}
265271

266272
/**
@@ -424,6 +430,16 @@ bool drm_crtc_helper_set_mode(struct drm_crtc *crtc,
424430

425431
if (encoder->crtc != crtc)
426432
continue;
433+
434+
if (encoder->bridge && encoder->bridge->funcs->mode_fixup) {
435+
ret = encoder->bridge->funcs->mode_fixup(
436+
encoder->bridge, mode, adjusted_mode);
437+
if (!ret) {
438+
DRM_DEBUG_KMS("Bridge fixup failed\n");
439+
goto done;
440+
}
441+
}
442+
427443
encoder_funcs = encoder->helper_private;
428444
if (!(ret = encoder_funcs->mode_fixup(encoder, mode,
429445
adjusted_mode))) {
@@ -443,9 +459,16 @@ bool drm_crtc_helper_set_mode(struct drm_crtc *crtc,
443459

444460
if (encoder->crtc != crtc)
445461
continue;
462+
463+
if (encoder->bridge)
464+
encoder->bridge->funcs->disable(encoder->bridge);
465+
446466
encoder_funcs = encoder->helper_private;
447467
/* Disable the encoders as the first thing we do. */
448468
encoder_funcs->prepare(encoder);
469+
470+
if (encoder->bridge)
471+
encoder->bridge->funcs->post_disable(encoder->bridge);
449472
}
450473

451474
drm_crtc_prepare_encoders(dev);
@@ -469,6 +492,10 @@ bool drm_crtc_helper_set_mode(struct drm_crtc *crtc,
469492
mode->base.id, mode->name);
470493
encoder_funcs = encoder->helper_private;
471494
encoder_funcs->mode_set(encoder, mode, adjusted_mode);
495+
496+
if (encoder->bridge && encoder->bridge->funcs->mode_set)
497+
encoder->bridge->funcs->mode_set(encoder->bridge, mode,
498+
adjusted_mode);
472499
}
473500

474501
/* Now enable the clocks, plane, pipe, and connectors that we set up. */
@@ -479,9 +506,14 @@ bool drm_crtc_helper_set_mode(struct drm_crtc *crtc,
479506
if (encoder->crtc != crtc)
480507
continue;
481508

509+
if (encoder->bridge)
510+
encoder->bridge->funcs->pre_enable(encoder->bridge);
511+
482512
encoder_funcs = encoder->helper_private;
483513
encoder_funcs->commit(encoder);
484514

515+
if (encoder->bridge)
516+
encoder->bridge->funcs->enable(encoder->bridge);
485517
}
486518

487519
/* Store real post-adjustment hardware mode. */
@@ -830,6 +862,31 @@ static int drm_helper_choose_encoder_dpms(struct drm_encoder *encoder)
830862
return dpms;
831863
}
832864

865+
/* Helper which handles bridge ordering around encoder dpms */
866+
static void drm_helper_encoder_dpms(struct drm_encoder *encoder, int mode)
867+
{
868+
struct drm_bridge *bridge = encoder->bridge;
869+
struct drm_encoder_helper_funcs *encoder_funcs;
870+
871+
if (bridge) {
872+
if (mode == DRM_MODE_DPMS_ON)
873+
bridge->funcs->pre_enable(bridge);
874+
else
875+
bridge->funcs->disable(bridge);
876+
}
877+
878+
encoder_funcs = encoder->helper_private;
879+
if (encoder_funcs->dpms)
880+
encoder_funcs->dpms(encoder, mode);
881+
882+
if (bridge) {
883+
if (mode == DRM_MODE_DPMS_ON)
884+
bridge->funcs->enable(bridge);
885+
else
886+
bridge->funcs->post_disable(bridge);
887+
}
888+
}
889+
833890
static int drm_helper_choose_crtc_dpms(struct drm_crtc *crtc)
834891
{
835892
int dpms = DRM_MODE_DPMS_OFF;
@@ -857,14 +914,17 @@ void drm_helper_connector_dpms(struct drm_connector *connector, int mode)
857914
{
858915
struct drm_encoder *encoder = connector->encoder;
859916
struct drm_crtc *crtc = encoder ? encoder->crtc : NULL;
860-
int old_dpms;
917+
int old_dpms, encoder_dpms = DRM_MODE_DPMS_OFF;
861918

862919
if (mode == connector->dpms)
863920
return;
864921

865922
old_dpms = connector->dpms;
866923
connector->dpms = mode;
867924

925+
if (encoder)
926+
encoder_dpms = drm_helper_choose_encoder_dpms(encoder);
927+
868928
/* from off to on, do crtc then encoder */
869929
if (mode < old_dpms) {
870930
if (crtc) {
@@ -873,22 +933,14 @@ void drm_helper_connector_dpms(struct drm_connector *connector, int mode)
873933
(*crtc_funcs->dpms) (crtc,
874934
drm_helper_choose_crtc_dpms(crtc));
875935
}
876-
if (encoder) {
877-
struct drm_encoder_helper_funcs *encoder_funcs = encoder->helper_private;
878-
if (encoder_funcs->dpms)
879-
(*encoder_funcs->dpms) (encoder,
880-
drm_helper_choose_encoder_dpms(encoder));
881-
}
936+
if (encoder)
937+
drm_helper_encoder_dpms(encoder, encoder_dpms);
882938
}
883939

884940
/* from on to off, do encoder then crtc */
885941
if (mode > old_dpms) {
886-
if (encoder) {
887-
struct drm_encoder_helper_funcs *encoder_funcs = encoder->helper_private;
888-
if (encoder_funcs->dpms)
889-
(*encoder_funcs->dpms) (encoder,
890-
drm_helper_choose_encoder_dpms(encoder));
891-
}
942+
if (encoder)
943+
drm_helper_encoder_dpms(encoder, encoder_dpms);
892944
if (crtc) {
893945
struct drm_crtc_helper_funcs *crtc_funcs = crtc->helper_private;
894946
if (crtc_funcs->dpms)
@@ -924,9 +976,8 @@ int drm_helper_resume_force_mode(struct drm_device *dev)
924976
{
925977
struct drm_crtc *crtc;
926978
struct drm_encoder *encoder;
927-
struct drm_encoder_helper_funcs *encoder_funcs;
928979
struct drm_crtc_helper_funcs *crtc_funcs;
929-
int ret;
980+
int ret, encoder_dpms;
930981

931982
list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) {
932983

@@ -946,10 +997,10 @@ int drm_helper_resume_force_mode(struct drm_device *dev)
946997
if(encoder->crtc != crtc)
947998
continue;
948999

949-
encoder_funcs = encoder->helper_private;
950-
if (encoder_funcs->dpms)
951-
(*encoder_funcs->dpms) (encoder,
952-
drm_helper_choose_encoder_dpms(encoder));
1000+
encoder_dpms = drm_helper_choose_encoder_dpms(
1001+
encoder);
1002+
1003+
drm_helper_encoder_dpms(encoder, encoder_dpms);
9531004
}
9541005

9551006
crtc_funcs = crtc->helper_private;

0 commit comments

Comments
 (0)