diff options
author | Sean Paul <seanpaul@chromium.org> | 2013-08-14 20:47:37 (GMT) |
---|---|---|
committer | Dave Airlie <airlied@redhat.com> | 2013-09-02 00:23:26 (GMT) |
commit | 3b336ec4c5460833ad7573d0b6e22793f6a389ab (patch) | |
tree | d82b0a12cc700203203d1236197a25b2c12967be /drivers/gpu/drm/drm_crtc_helper.c | |
parent | 2254f637dbd18f6432da526552d19a616ffbf8d6 (diff) | |
download | linux-fsl-qoriq-3b336ec4c5460833ad7573d0b6e22793f6a389ab.tar.xz |
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 <seanpaul@chromium.org>
Acked-by: Daniel Vetter <daniel.vetter@ffwll.ch>
Reviewed-by: Rob Clark <robdclark@gmail.com>
Signed-off-by: Dave Airlie <airlied@redhat.com>
Diffstat (limited to 'drivers/gpu/drm/drm_crtc_helper.c')
-rw-r--r-- | drivers/gpu/drm/drm_crtc_helper.c | 89 |
1 files changed, 70 insertions, 19 deletions
diff --git a/drivers/gpu/drm/drm_crtc_helper.c b/drivers/gpu/drm/drm_crtc_helper.c index 6a64749..c722c3b 100644 --- a/drivers/gpu/drm/drm_crtc_helper.c +++ b/drivers/gpu/drm/drm_crtc_helper.c @@ -257,10 +257,16 @@ drm_encoder_disable(struct drm_encoder *encoder) { struct drm_encoder_helper_funcs *encoder_funcs = encoder->helper_private; + if (encoder->bridge) + encoder->bridge->funcs->disable(encoder->bridge); + if (encoder_funcs->disable) (*encoder_funcs->disable)(encoder); else (*encoder_funcs->dpms)(encoder, DRM_MODE_DPMS_OFF); + + if (encoder->bridge) + encoder->bridge->funcs->post_disable(encoder->bridge); } /** @@ -424,6 +430,16 @@ bool drm_crtc_helper_set_mode(struct drm_crtc *crtc, if (encoder->crtc != crtc) continue; + + if (encoder->bridge && encoder->bridge->funcs->mode_fixup) { + ret = encoder->bridge->funcs->mode_fixup( + encoder->bridge, mode, adjusted_mode); + if (!ret) { + DRM_DEBUG_KMS("Bridge fixup failed\n"); + goto done; + } + } + encoder_funcs = encoder->helper_private; if (!(ret = encoder_funcs->mode_fixup(encoder, mode, adjusted_mode))) { @@ -443,9 +459,16 @@ bool drm_crtc_helper_set_mode(struct drm_crtc *crtc, if (encoder->crtc != crtc) continue; + + if (encoder->bridge) + encoder->bridge->funcs->disable(encoder->bridge); + encoder_funcs = encoder->helper_private; /* Disable the encoders as the first thing we do. */ encoder_funcs->prepare(encoder); + + if (encoder->bridge) + encoder->bridge->funcs->post_disable(encoder->bridge); } drm_crtc_prepare_encoders(dev); @@ -469,6 +492,10 @@ bool drm_crtc_helper_set_mode(struct drm_crtc *crtc, mode->base.id, mode->name); encoder_funcs = encoder->helper_private; encoder_funcs->mode_set(encoder, mode, adjusted_mode); + + if (encoder->bridge && encoder->bridge->funcs->mode_set) + encoder->bridge->funcs->mode_set(encoder->bridge, mode, + adjusted_mode); } /* 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, if (encoder->crtc != crtc) continue; + if (encoder->bridge) + encoder->bridge->funcs->pre_enable(encoder->bridge); + encoder_funcs = encoder->helper_private; encoder_funcs->commit(encoder); + if (encoder->bridge) + encoder->bridge->funcs->enable(encoder->bridge); } /* Store real post-adjustment hardware mode. */ @@ -830,6 +862,31 @@ static int drm_helper_choose_encoder_dpms(struct drm_encoder *encoder) return dpms; } +/* Helper which handles bridge ordering around encoder dpms */ +static void drm_helper_encoder_dpms(struct drm_encoder *encoder, int mode) +{ + struct drm_bridge *bridge = encoder->bridge; + struct drm_encoder_helper_funcs *encoder_funcs; + + if (bridge) { + if (mode == DRM_MODE_DPMS_ON) + bridge->funcs->pre_enable(bridge); + else + bridge->funcs->disable(bridge); + } + + encoder_funcs = encoder->helper_private; + if (encoder_funcs->dpms) + encoder_funcs->dpms(encoder, mode); + + if (bridge) { + if (mode == DRM_MODE_DPMS_ON) + bridge->funcs->enable(bridge); + else + bridge->funcs->post_disable(bridge); + } +} + static int drm_helper_choose_crtc_dpms(struct drm_crtc *crtc) { int dpms = DRM_MODE_DPMS_OFF; @@ -857,7 +914,7 @@ void drm_helper_connector_dpms(struct drm_connector *connector, int mode) { struct drm_encoder *encoder = connector->encoder; struct drm_crtc *crtc = encoder ? encoder->crtc : NULL; - int old_dpms; + int old_dpms, encoder_dpms = DRM_MODE_DPMS_OFF; if (mode == connector->dpms) return; @@ -865,6 +922,9 @@ void drm_helper_connector_dpms(struct drm_connector *connector, int mode) old_dpms = connector->dpms; connector->dpms = mode; + if (encoder) + encoder_dpms = drm_helper_choose_encoder_dpms(encoder); + /* from off to on, do crtc then encoder */ if (mode < old_dpms) { if (crtc) { @@ -873,22 +933,14 @@ void drm_helper_connector_dpms(struct drm_connector *connector, int mode) (*crtc_funcs->dpms) (crtc, drm_helper_choose_crtc_dpms(crtc)); } - if (encoder) { - struct drm_encoder_helper_funcs *encoder_funcs = encoder->helper_private; - if (encoder_funcs->dpms) - (*encoder_funcs->dpms) (encoder, - drm_helper_choose_encoder_dpms(encoder)); - } + if (encoder) + drm_helper_encoder_dpms(encoder, encoder_dpms); } /* from on to off, do encoder then crtc */ if (mode > old_dpms) { - if (encoder) { - struct drm_encoder_helper_funcs *encoder_funcs = encoder->helper_private; - if (encoder_funcs->dpms) - (*encoder_funcs->dpms) (encoder, - drm_helper_choose_encoder_dpms(encoder)); - } + if (encoder) + drm_helper_encoder_dpms(encoder, encoder_dpms); if (crtc) { struct drm_crtc_helper_funcs *crtc_funcs = crtc->helper_private; if (crtc_funcs->dpms) @@ -924,9 +976,8 @@ int drm_helper_resume_force_mode(struct drm_device *dev) { struct drm_crtc *crtc; struct drm_encoder *encoder; - struct drm_encoder_helper_funcs *encoder_funcs; struct drm_crtc_helper_funcs *crtc_funcs; - int ret; + int ret, encoder_dpms; list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) { @@ -946,10 +997,10 @@ int drm_helper_resume_force_mode(struct drm_device *dev) if(encoder->crtc != crtc) continue; - encoder_funcs = encoder->helper_private; - if (encoder_funcs->dpms) - (*encoder_funcs->dpms) (encoder, - drm_helper_choose_encoder_dpms(encoder)); + encoder_dpms = drm_helper_choose_encoder_dpms( + encoder); + + drm_helper_encoder_dpms(encoder, encoder_dpms); } crtc_funcs = crtc->helper_private; |