From 8f1628bf936cc61fd33e4a7de34e693e6c432d7b Mon Sep 17 00:00:00 2001 From: Hu Tiger Chen Date: Tue, 31 Jan 2012 00:17:17 +0200 Subject: [PATCH] MUST_REVERT: Avoid calling mode set for MIPI during HDMI hotplug. Currently, during HDMI hotplug/unplug, the MIPI mode set is invoked along with HDMI mode set. The MIPI mode set during HDMI hotplug causes the system to hang due to an i2c transaction failure for MIPI. Till the local display issue is fixed, we avoid calling the MIPI mode set on every HDMI hotplug event. Signed-off-by: Arun Kannan Signed-off-by: Kirill A. Shutemov --- drivers/gpu/drm/drm_crtc_helper.c | 32 +++++++++++++++++++++++++++++++- drivers/gpu/drm/drm_fb_helper.c | 6 +++++- drivers/staging/mrst/drv/psb_fb.c | 2 ++ include/drm/drm_fb_helper.h | 2 ++ 4 files changed, 40 insertions(+), 2 deletions(-) diff --git a/drivers/gpu/drm/drm_crtc_helper.c b/drivers/gpu/drm/drm_crtc_helper.c index 836e2ae..1844849 100644 --- a/drivers/gpu/drm/drm_crtc_helper.c +++ b/drivers/gpu/drm/drm_crtc_helper.c @@ -478,10 +478,13 @@ int drm_crtc_helper_set_config(struct drm_mode_set *set) bool mode_changed = false; /* if true do a full mode set */ bool fb_changed = false; /* if true and !mode_changed just do a flip */ struct drm_connector *save_connectors, *connector; + struct drm_connector *hdmiconnector = NULL; int count = 0, ro, fail = 0; struct drm_crtc_helper_funcs *crtc_funcs; int ret = 0; int i; + /* true if this is triggerred from hotplug event*/ + bool in_hotplug = false; DRM_DEBUG_KMS("\n"); @@ -652,7 +655,34 @@ int drm_crtc_helper_set_config(struct drm_mode_set *set) if (mode_changed) { set->crtc->enabled = drm_helper_crtc_in_use(set->crtc); - if (set->crtc->enabled) { + /* check whether the crtc is used for HDMI output */ + list_for_each_entry(connector, + &dev->mode_config.connector_list, head) { + if (!connector->encoder) + continue; + if ((connector->encoder->crtc == set->crtc) && + (connector->connector_type + == DRM_MODE_CONNECTOR_DVID)) { + hdmiconnector = connector; + break; + } + } + + /* check whether this is from HDMI hotplug */ + if (set->fb) { + struct drm_fb_helper *fb_helper = + (struct drm_fb_helper *)set->fb->helper_private; + if (fb_helper) + in_hotplug = fb_helper->hotplug; + } + + /* FIXME: This is workaround of i2c failure when setup local + * MIPI in hotplug sequence. + * We only set mode for HDMI pipe in HDMI hotplug sequence. + * This should be reverted after fix the bug. + */ + if (set->crtc->enabled && + (hdmiconnector || !in_hotplug)) { DRM_DEBUG_KMS("attempting to set mode from" " userspace\n"); drm_mode_debug_printmodeline(set->mode); diff --git a/drivers/gpu/drm/drm_fb_helper.c b/drivers/gpu/drm/drm_fb_helper.c index 802b61a..594f4ae 100644 --- a/drivers/gpu/drm/drm_fb_helper.c +++ b/drivers/gpu/drm/drm_fb_helper.c @@ -1402,10 +1402,12 @@ int drm_fb_helper_hotplug_event(struct drm_fb_helper *fb_helper) u32 max_width, max_height, bpp_sel; bool bound = false, crtcs_bound = false; struct drm_crtc *crtc; + int ret; if (!fb_helper->fb) return 0; + fb_helper->hotplug = true; mutex_lock(&dev->mode_config.mutex); list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) { if (crtc->fb) @@ -1430,7 +1432,9 @@ int drm_fb_helper_hotplug_event(struct drm_fb_helper *fb_helper) drm_setup_crtcs(fb_helper); mutex_unlock(&dev->mode_config.mutex); - return drm_fb_helper_single_fb_probe(fb_helper, bpp_sel); + ret = drm_fb_helper_single_fb_probe(fb_helper, bpp_sel); + fb_helper->hotplug = false; + return ret; } EXPORT_SYMBOL(drm_fb_helper_hotplug_event); diff --git a/drivers/staging/mrst/drv/psb_fb.c b/drivers/staging/mrst/drv/psb_fb.c index 64e76c9..dd3a278 100644 --- a/drivers/staging/mrst/drv/psb_fb.c +++ b/drivers/staging/mrst/drv/psb_fb.c @@ -330,6 +330,7 @@ static struct drm_framebuffer *psb_user_framebuffer_create psbfb->fbdev = info; fbdev->pfb = psbfb; + fb->helper_private = &(fbdev->psb_fb_helper); fbdev->psb_fb_helper.fb = fb; fbdev->psb_fb_helper.fbdev = info; MRSTLFBHandleChangeFB(dev, psbfb); @@ -384,6 +385,7 @@ static int psbfb_create(struct psb_fbdev * fbdev, struct drm_fb_helper_surface_s psbfb->fbdev = info; + fb->helper_private = &(fbdev->psb_fb_helper); fbdev->psb_fb_helper.fb = fb; fbdev->psb_fb_helper.fbdev = info; fbdev->pfb = psbfb; diff --git a/include/drm/drm_fb_helper.h b/include/drm/drm_fb_helper.h index 6e3076a..0c57121 100644 --- a/include/drm/drm_fb_helper.h +++ b/include/drm/drm_fb_helper.h @@ -82,6 +82,8 @@ struct drm_fb_helper { /* we got a hotplug but fbdev wasn't running the console delay until next set_par */ bool delayed_hotplug; + /* indicate we are in the process of one hotplug */ + bool hotplug; }; int drm_fb_helper_single_fb_probe(struct drm_fb_helper *helper, -- 2.7.4