From bbb0aef5cfe95fe9b51a7eeba4a440b69037b01f Mon Sep 17 00:00:00 2001 From: Joe Perches Date: Sun, 17 Apr 2011 20:35:52 -0700 Subject: drm: Verify debug message arguments Add __attribute__((format (printf, 4, 5))) to drm_ut_debug_printk and fix fallout. Signed-off-by: Joe Perches Signed-off-by: Dave Airlie --- drivers/gpu/drm/i915/intel_display.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'drivers/gpu/drm/i915/intel_display.c') diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c index e522c70..21a7e70 100644 --- a/drivers/gpu/drm/i915/intel_display.c +++ b/drivers/gpu/drm/i915/intel_display.c @@ -3497,11 +3497,11 @@ static unsigned long intel_calculate_wm(unsigned long clock_in_khz, 1000; entries_required = DIV_ROUND_UP(entries_required, wm->cacheline_size); - DRM_DEBUG_KMS("FIFO entries required for mode: %d\n", entries_required); + DRM_DEBUG_KMS("FIFO entries required for mode: %ld\n", entries_required); wm_size = fifo_size - (entries_required + wm->guard_size); - DRM_DEBUG_KMS("FIFO watermark level: %d\n", wm_size); + DRM_DEBUG_KMS("FIFO watermark level: %ld\n", wm_size); /* Don't promote wm_size to unsigned... */ if (wm_size > (long)wm->max_wm) @@ -3823,13 +3823,13 @@ static bool g4x_check_srwm(struct drm_device *dev, display_wm, cursor_wm); if (display_wm > display->max_wm) { - DRM_DEBUG_KMS("display watermark is too large(%d), disabling\n", + DRM_DEBUG_KMS("display watermark is too large(%d/%ld), disabling\n", display_wm, display->max_wm); return false; } if (cursor_wm > cursor->max_wm) { - DRM_DEBUG_KMS("cursor watermark is too large(%d), disabling\n", + DRM_DEBUG_KMS("cursor watermark is too large(%d/%ld), disabling\n", cursor_wm, cursor->max_wm); return false; } -- cgit v1.1 From 7173188d5d5e50b95c588dbae3b3bc78fde4138e Mon Sep 17 00:00:00 2001 From: Chris Wilson Date: Tue, 19 Apr 2011 23:10:58 +0100 Subject: drm/i915: Simplify return value from intel_get_load_detect_pipe ... and so remove the confusion as to whether to use the returned crtc or intel_encoder->base.crtc with the subsequent load-detection. Even though they were the same, the two instances of load-detection code disagreed over which was the more correct. Signed-off-by: Chris Wilson Signed-off-by: Keith Packard --- drivers/gpu/drm/i915/intel_display.c | 16 +++++++++------- 1 file changed, 9 insertions(+), 7 deletions(-) (limited to 'drivers/gpu/drm/i915/intel_display.c') diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c index 373c2a0..228621d 100644 --- a/drivers/gpu/drm/i915/intel_display.c +++ b/drivers/gpu/drm/i915/intel_display.c @@ -5481,10 +5481,10 @@ static struct drm_display_mode load_detect_mode = { 704, 832, 0, 480, 489, 491, 520, 0, DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_NVSYNC), }; -struct drm_crtc *intel_get_load_detect_pipe(struct intel_encoder *intel_encoder, - struct drm_connector *connector, - struct drm_display_mode *mode, - int *dpms_mode) +bool intel_get_load_detect_pipe(struct intel_encoder *intel_encoder, + struct drm_connector *connector, + struct drm_display_mode *mode, + int *dpms_mode) { struct intel_crtc *intel_crtc; struct drm_crtc *possible_crtc; @@ -5517,7 +5517,7 @@ struct drm_crtc *intel_get_load_detect_pipe(struct intel_encoder *intel_encoder, crtc_funcs->dpms(crtc, DRM_MODE_DPMS_ON); encoder_funcs->dpms(encoder, DRM_MODE_DPMS_ON); } - return crtc; + return true; } /* Find an unused one (if possible) */ @@ -5537,7 +5537,8 @@ struct drm_crtc *intel_get_load_detect_pipe(struct intel_encoder *intel_encoder, * If we didn't find an unused CRTC, don't use any. */ if (!crtc) { - return NULL; + DRM_DEBUG_KMS("no pipe available for load-detect\n"); + return false; } encoder->crtc = crtc; @@ -5561,10 +5562,11 @@ struct drm_crtc *intel_get_load_detect_pipe(struct intel_encoder *intel_encoder, encoder_funcs->mode_set(encoder, &crtc->mode, &crtc->mode); encoder_funcs->commit(encoder); } + /* let the connector get through one full cycle before testing */ intel_wait_for_vblank(dev, intel_crtc->pipe); - return crtc; + return true; } void intel_release_load_detect_pipe(struct intel_encoder *intel_encoder, -- cgit v1.1 From be925587570a745944d99042368f72496bc28a70 Mon Sep 17 00:00:00 2001 From: Chris Wilson Date: Wed, 20 Apr 2011 19:20:15 +0100 Subject: drm/i915: Propagate failure to set mode for load-detect pipe Check the return value from drm_crtc_set_mode(), report the failure via a debug message and propagate the error back to the caller. This prevents us from blissfully continuing to do the load detection on a disabled pipe. Fortunately actual failure for modesetting is very rare, and reported failures even rarer. Signed-off-by: Chris Wilson Signed-off-by: Keith Packard --- drivers/gpu/drm/i915/intel_display.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) (limited to 'drivers/gpu/drm/i915/intel_display.c') diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c index 228621d..943bcbc 100644 --- a/drivers/gpu/drm/i915/intel_display.c +++ b/drivers/gpu/drm/i915/intel_display.c @@ -5551,7 +5551,11 @@ bool intel_get_load_detect_pipe(struct intel_encoder *intel_encoder, if (!crtc->enabled) { if (!mode) mode = &load_detect_mode; - drm_crtc_helper_set_mode(crtc, mode, 0, 0, crtc->fb); + + if (!drm_crtc_helper_set_mode(crtc, mode, 0, 0, crtc->fb)) { + DRM_DEBUG_KMS("failed to set mode on load-detect pipe\n"); + return false; + } } else { if (intel_crtc->dpms_mode != DRM_MODE_DPMS_ON) { crtc_funcs = crtc->helper_private; -- cgit v1.1 From 8261b19173b89d86cc3088483595e2879e4976d6 Mon Sep 17 00:00:00 2001 From: Chris Wilson Date: Tue, 19 Apr 2011 23:18:09 +0100 Subject: drm/i915: Don't store temporary load-detect variables in the generic encoder Keep all the state required for undoing and restoring the previous pipe configuration together in a single struct passed from intel_get_load_detect_pipe() to intel_release_load_detect_pipe() rather than stuffing them inside the common encoder structure. Signed-off-by: Chris Wilson Reviewed-by: Keith Packard Signed-off-by: Keith Packard --- drivers/gpu/drm/i915/intel_display.c | 26 +++++++++++++++----------- 1 file changed, 15 insertions(+), 11 deletions(-) (limited to 'drivers/gpu/drm/i915/intel_display.c') diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c index 943bcbc..81c4f59 100644 --- a/drivers/gpu/drm/i915/intel_display.c +++ b/drivers/gpu/drm/i915/intel_display.c @@ -5484,7 +5484,7 @@ static struct drm_display_mode load_detect_mode = { bool intel_get_load_detect_pipe(struct intel_encoder *intel_encoder, struct drm_connector *connector, struct drm_display_mode *mode, - int *dpms_mode) + struct intel_load_detect_pipe *old) { struct intel_crtc *intel_crtc; struct drm_crtc *possible_crtc; @@ -5509,14 +5509,18 @@ bool intel_get_load_detect_pipe(struct intel_encoder *intel_encoder, /* See if we already have a CRTC for this connector */ if (encoder->crtc) { crtc = encoder->crtc; - /* Make sure the crtc and connector are running */ + intel_crtc = to_intel_crtc(crtc); - *dpms_mode = intel_crtc->dpms_mode; + old->dpms_mode = intel_crtc->dpms_mode; + old->load_detect_temp = false; + + /* Make sure the crtc and connector are running */ if (intel_crtc->dpms_mode != DRM_MODE_DPMS_ON) { crtc_funcs = crtc->helper_private; crtc_funcs->dpms(crtc, DRM_MODE_DPMS_ON); encoder_funcs->dpms(encoder, DRM_MODE_DPMS_ON); } + return true; } @@ -5543,10 +5547,10 @@ bool intel_get_load_detect_pipe(struct intel_encoder *intel_encoder, encoder->crtc = crtc; connector->encoder = encoder; - intel_encoder->load_detect_temp = true; intel_crtc = to_intel_crtc(crtc); - *dpms_mode = intel_crtc->dpms_mode; + old->dpms_mode = intel_crtc->dpms_mode; + old->load_detect_temp = true; if (!crtc->enabled) { if (!mode) @@ -5574,7 +5578,8 @@ bool intel_get_load_detect_pipe(struct intel_encoder *intel_encoder, } void intel_release_load_detect_pipe(struct intel_encoder *intel_encoder, - struct drm_connector *connector, int dpms_mode) + struct drm_connector *connector, + struct intel_load_detect_pipe *old) { struct drm_encoder *encoder = &intel_encoder->base; struct drm_device *dev = encoder->dev; @@ -5582,19 +5587,18 @@ void intel_release_load_detect_pipe(struct intel_encoder *intel_encoder, struct drm_encoder_helper_funcs *encoder_funcs = encoder->helper_private; struct drm_crtc_helper_funcs *crtc_funcs = crtc->helper_private; - if (intel_encoder->load_detect_temp) { + if (old->load_detect_temp) { encoder->crtc = NULL; connector->encoder = NULL; - intel_encoder->load_detect_temp = false; crtc->enabled = drm_helper_crtc_in_use(crtc); drm_helper_disable_unused_functions(dev); } /* Switch crtc and encoder back off if necessary */ - if (crtc->enabled && dpms_mode != DRM_MODE_DPMS_ON) { + if (crtc->enabled && old->dpms_mode != DRM_MODE_DPMS_ON) { if (encoder->crtc == crtc) - encoder_funcs->dpms(encoder, dpms_mode); - crtc_funcs->dpms(crtc, dpms_mode); + encoder_funcs->dpms(encoder, old->dpms_mode); + crtc_funcs->dpms(crtc, old->dpms_mode); } } -- cgit v1.1 From 7a5e4805bda3c6420e96ca0626c3fa23dd281e96 Mon Sep 17 00:00:00 2001 From: Chris Wilson Date: Tue, 19 Apr 2011 23:21:12 +0100 Subject: drm/i915: Remove unused supported_crtc from intel_load_detect_pipe ... and the no longer relevant comment. The code ceased stealing a pipe for load detection a long time ago. Signed-off-by: Chris Wilson Reviewed-by: Keith Packard Signed-off-by: Keith Packard --- drivers/gpu/drm/i915/intel_display.c | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) (limited to 'drivers/gpu/drm/i915/intel_display.c') diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c index 81c4f59..dfa965a 100644 --- a/drivers/gpu/drm/i915/intel_display.c +++ b/drivers/gpu/drm/i915/intel_display.c @@ -5488,7 +5488,6 @@ bool intel_get_load_detect_pipe(struct intel_encoder *intel_encoder, { struct intel_crtc *intel_crtc; struct drm_crtc *possible_crtc; - struct drm_crtc *supported_crtc =NULL; struct drm_encoder *encoder = &intel_encoder->base; struct drm_crtc *crtc = NULL; struct drm_device *dev = encoder->dev; @@ -5498,12 +5497,12 @@ bool intel_get_load_detect_pipe(struct intel_encoder *intel_encoder, /* * Algorithm gets a little messy: + * * - if the connector already has an assigned crtc, use it (but make * sure it's on first) + * * - try to find the first unused crtc that can drive this connector, * and use that if we find one - * - if there are no unused crtcs available, try to use the first - * one we found that supports the connector */ /* See if we already have a CRTC for this connector */ @@ -5533,8 +5532,6 @@ bool intel_get_load_detect_pipe(struct intel_encoder *intel_encoder, crtc = possible_crtc; break; } - if (!supported_crtc) - supported_crtc = possible_crtc; } /* -- cgit v1.1 From 4fbf69138ab3aa28a8f92512b7417d3d1829a086 Mon Sep 17 00:00:00 2001 From: Chris Wilson Date: Wed, 20 Apr 2011 00:23:12 +0100 Subject: drm/i915: Pass the saved adjusted_mode when adding to the load-detect crtc Signed-off-by: Chris Wilson Reviewed-by: Keith Packard Signed-off-by: Keith Packard --- drivers/gpu/drm/i915/intel_display.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/gpu/drm/i915/intel_display.c') diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c index dfa965a..e857a83 100644 --- a/drivers/gpu/drm/i915/intel_display.c +++ b/drivers/gpu/drm/i915/intel_display.c @@ -5564,7 +5564,7 @@ bool intel_get_load_detect_pipe(struct intel_encoder *intel_encoder, } /* Add this connector to the crtc */ - encoder_funcs->mode_set(encoder, &crtc->mode, &crtc->mode); + encoder_funcs->mode_set(encoder, &crtc->mode, &crtc->hwmode); encoder_funcs->commit(encoder); } -- cgit v1.1 From 6492711d05b85f9794809cb4a961ce8cdc6fa720 Mon Sep 17 00:00:00 2001 From: Chris Wilson Date: Wed, 20 Apr 2011 07:25:26 +0100 Subject: drm/i915: Remove dead code from intel_get_load_detect_pipe() As we only allow the use of a disabled CRTC, we don't need to handle the case where we are reusing an already enabled pipe. Signed-off-by: Chris Wilson Reviewed-by: Keith Packard Signed-off-by: Keith Packard --- drivers/gpu/drm/i915/intel_display.c | 28 ++++++++++------------------ 1 file changed, 10 insertions(+), 18 deletions(-) (limited to 'drivers/gpu/drm/i915/intel_display.c') diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c index e857a83..7413a07 100644 --- a/drivers/gpu/drm/i915/intel_display.c +++ b/drivers/gpu/drm/i915/intel_display.c @@ -5491,8 +5491,6 @@ bool intel_get_load_detect_pipe(struct intel_encoder *intel_encoder, struct drm_encoder *encoder = &intel_encoder->base; struct drm_crtc *crtc = NULL; struct drm_device *dev = encoder->dev; - struct drm_encoder_helper_funcs *encoder_funcs = encoder->helper_private; - struct drm_crtc_helper_funcs *crtc_funcs; int i = -1; /* @@ -5515,8 +5513,13 @@ bool intel_get_load_detect_pipe(struct intel_encoder *intel_encoder, /* Make sure the crtc and connector are running */ if (intel_crtc->dpms_mode != DRM_MODE_DPMS_ON) { + struct drm_encoder_helper_funcs *encoder_funcs; + struct drm_crtc_helper_funcs *crtc_funcs; + crtc_funcs = crtc->helper_private; crtc_funcs->dpms(crtc, DRM_MODE_DPMS_ON); + + encoder_funcs = encoder->helper_private; encoder_funcs->dpms(encoder, DRM_MODE_DPMS_ON); } @@ -5549,23 +5552,12 @@ bool intel_get_load_detect_pipe(struct intel_encoder *intel_encoder, old->dpms_mode = intel_crtc->dpms_mode; old->load_detect_temp = true; - if (!crtc->enabled) { - if (!mode) - mode = &load_detect_mode; - - if (!drm_crtc_helper_set_mode(crtc, mode, 0, 0, crtc->fb)) { - DRM_DEBUG_KMS("failed to set mode on load-detect pipe\n"); - return false; - } - } else { - if (intel_crtc->dpms_mode != DRM_MODE_DPMS_ON) { - crtc_funcs = crtc->helper_private; - crtc_funcs->dpms(crtc, DRM_MODE_DPMS_ON); - } + if (!mode) + mode = &load_detect_mode; - /* Add this connector to the crtc */ - encoder_funcs->mode_set(encoder, &crtc->mode, &crtc->hwmode); - encoder_funcs->commit(encoder); + if (!drm_crtc_helper_set_mode(crtc, mode, 0, 0, crtc->fb)) { + DRM_DEBUG_KMS("failed to set mode on load-detect pipe\n"); + return false; } /* let the connector get through one full cycle before testing */ -- cgit v1.1 From 0622a53c60fbf48d3b85efc4995f4c152c254cf4 Mon Sep 17 00:00:00 2001 From: Chris Wilson Date: Thu, 21 Apr 2011 09:32:11 +0100 Subject: drm/i915: Remove dead code from intel_release_load_detect_pipe() As we now never attempt to steal a crtc for load detection, we either set a mode on a new pipe, or change the dpms mode on an existing pipe. Never both, so we can simplify the code slightly. Signed-off-by: Chris Wilson Signed-off-by: Keith Packard --- drivers/gpu/drm/i915/intel_display.c | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) (limited to 'drivers/gpu/drm/i915/intel_display.c') diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c index 7413a07..e1fcd89 100644 --- a/drivers/gpu/drm/i915/intel_display.c +++ b/drivers/gpu/drm/i915/intel_display.c @@ -5577,16 +5577,14 @@ void intel_release_load_detect_pipe(struct intel_encoder *intel_encoder, struct drm_crtc_helper_funcs *crtc_funcs = crtc->helper_private; if (old->load_detect_temp) { - encoder->crtc = NULL; connector->encoder = NULL; - crtc->enabled = drm_helper_crtc_in_use(crtc); drm_helper_disable_unused_functions(dev); + return; } /* Switch crtc and encoder back off if necessary */ - if (crtc->enabled && old->dpms_mode != DRM_MODE_DPMS_ON) { - if (encoder->crtc == crtc) - encoder_funcs->dpms(encoder, old->dpms_mode); + if (old->dpms_mode != DRM_MODE_DPMS_ON) { + encoder_funcs->dpms(encoder, old->dpms_mode); crtc_funcs->dpms(crtc, old->dpms_mode); } } -- cgit v1.1 From d2dff872ac44540622ef77a2b7d6ce4a1b145931 Mon Sep 17 00:00:00 2001 From: Chris Wilson Date: Tue, 19 Apr 2011 08:36:26 +0100 Subject: drm/i915: Attach a fb to the load-detect pipe We need to ensure that we feed valid memory into the display plane attached to the pipe when switching the pipe on. Otherwise, the display engine may read through an invalid PTE and so throw an PGTBL_ER exception. As we need to perform load detection before even the first object is allocated for the fbdev, there is no pre-existing object large enough for us to borrow to use as the framebuffer. So we need to create one and cleanup afterwards. At other times, the current fbcon may be large enough for us to borrow it for duration of load detection. Found by assert_fb_bound_for_plane(). Reported-by: Knut Petersen References: https://bugs.freedesktop.org/show_bug.cgi?id=36246 Signed-off-by: Chris Wilson Signed-off-by: Keith Packard --- drivers/gpu/drm/i915/intel_display.c | 144 ++++++++++++++++++++++++++++++----- 1 file changed, 127 insertions(+), 17 deletions(-) (limited to 'drivers/gpu/drm/i915/intel_display.c') diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c index e1fcd89..a47e5ee 100644 --- a/drivers/gpu/drm/i915/intel_display.c +++ b/drivers/gpu/drm/i915/intel_display.c @@ -5481,6 +5481,92 @@ static struct drm_display_mode load_detect_mode = { 704, 832, 0, 480, 489, 491, 520, 0, DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_NVSYNC), }; +static struct drm_framebuffer * +intel_framebuffer_create(struct drm_device *dev, + struct drm_mode_fb_cmd *mode_cmd, + struct drm_i915_gem_object *obj) +{ + struct intel_framebuffer *intel_fb; + int ret; + + intel_fb = kzalloc(sizeof(*intel_fb), GFP_KERNEL); + if (!intel_fb) { + drm_gem_object_unreference_unlocked(&obj->base); + return ERR_PTR(-ENOMEM); + } + + ret = intel_framebuffer_init(dev, intel_fb, mode_cmd, obj); + if (ret) { + drm_gem_object_unreference_unlocked(&obj->base); + kfree(intel_fb); + return ERR_PTR(ret); + } + + return &intel_fb->base; +} + +static u32 +intel_framebuffer_pitch_for_width(int width, int bpp) +{ + u32 pitch = DIV_ROUND_UP(width * bpp, 8); + return ALIGN(pitch, 64); +} + +static u32 +intel_framebuffer_size_for_mode(struct drm_display_mode *mode, int bpp) +{ + u32 pitch = intel_framebuffer_pitch_for_width(mode->hdisplay, bpp); + return ALIGN(pitch * mode->vdisplay, PAGE_SIZE); +} + +static struct drm_framebuffer * +intel_framebuffer_create_for_mode(struct drm_device *dev, + struct drm_display_mode *mode, + int depth, int bpp) +{ + struct drm_i915_gem_object *obj; + struct drm_mode_fb_cmd mode_cmd; + + obj = i915_gem_alloc_object(dev, + intel_framebuffer_size_for_mode(mode, bpp)); + if (obj == NULL) + return ERR_PTR(-ENOMEM); + + mode_cmd.width = mode->hdisplay; + mode_cmd.height = mode->vdisplay; + mode_cmd.depth = depth; + mode_cmd.bpp = bpp; + mode_cmd.pitch = intel_framebuffer_pitch_for_width(mode_cmd.width, bpp); + + return intel_framebuffer_create(dev, &mode_cmd, obj); +} + +static struct drm_framebuffer * +mode_fits_in_fbdev(struct drm_device *dev, + struct drm_display_mode *mode) +{ + struct drm_i915_private *dev_priv = dev->dev_private; + struct drm_i915_gem_object *obj; + struct drm_framebuffer *fb; + + if (dev_priv->fbdev == NULL) + return NULL; + + obj = dev_priv->fbdev->ifb.obj; + if (obj == NULL) + return NULL; + + fb = &dev_priv->fbdev->ifb.base; + if (fb->pitch < intel_framebuffer_pitch_for_width(mode->hdisplay, + fb->bits_per_pixel)) + return NULL; + + if (obj->base.size < mode->vdisplay * fb->pitch) + return NULL; + + return fb; +} + bool intel_get_load_detect_pipe(struct intel_encoder *intel_encoder, struct drm_connector *connector, struct drm_display_mode *mode, @@ -5491,8 +5577,13 @@ bool intel_get_load_detect_pipe(struct intel_encoder *intel_encoder, struct drm_encoder *encoder = &intel_encoder->base; struct drm_crtc *crtc = NULL; struct drm_device *dev = encoder->dev; + struct drm_framebuffer *old_fb; int i = -1; + DRM_DEBUG_KMS("[CONNECTOR:%d:%s], [ENCODER:%d:%s]\n", + connector->base.id, drm_get_connector_name(connector), + encoder->base.id, drm_get_encoder_name(encoder)); + /* * Algorithm gets a little messy: * @@ -5551,12 +5642,38 @@ bool intel_get_load_detect_pipe(struct intel_encoder *intel_encoder, intel_crtc = to_intel_crtc(crtc); old->dpms_mode = intel_crtc->dpms_mode; old->load_detect_temp = true; + old->release_fb = NULL; if (!mode) mode = &load_detect_mode; - if (!drm_crtc_helper_set_mode(crtc, mode, 0, 0, crtc->fb)) { + old_fb = crtc->fb; + + /* We need a framebuffer large enough to accommodate all accesses + * that the plane may generate whilst we perform load detection. + * We can not rely on the fbcon either being present (we get called + * during its initialisation to detect all boot displays, or it may + * not even exist) or that it is large enough to satisfy the + * requested mode. + */ + crtc->fb = mode_fits_in_fbdev(dev, mode); + if (crtc->fb == NULL) { + DRM_DEBUG_KMS("creating tmp fb for load-detection\n"); + crtc->fb = intel_framebuffer_create_for_mode(dev, mode, 24, 32); + old->release_fb = crtc->fb; + } else + DRM_DEBUG_KMS("reusing fbdev for load-detection framebuffer\n"); + if (IS_ERR(crtc->fb)) { + DRM_DEBUG_KMS("failed to allocate framebuffer for load-detection\n"); + crtc->fb = old_fb; + return false; + } + + if (!drm_crtc_helper_set_mode(crtc, mode, 0, 0, old_fb)) { DRM_DEBUG_KMS("failed to set mode on load-detect pipe\n"); + if (old->release_fb) + old->release_fb->funcs->destroy(old->release_fb); + crtc->fb = old_fb; return false; } @@ -5576,9 +5693,17 @@ void intel_release_load_detect_pipe(struct intel_encoder *intel_encoder, struct drm_encoder_helper_funcs *encoder_funcs = encoder->helper_private; struct drm_crtc_helper_funcs *crtc_funcs = crtc->helper_private; + DRM_DEBUG_KMS("[CONNECTOR:%d:%s], [ENCODER:%d:%s]\n", + connector->base.id, drm_get_connector_name(connector), + encoder->base.id, drm_get_encoder_name(encoder)); + if (old->load_detect_temp) { connector->encoder = NULL; drm_helper_disable_unused_functions(dev); + + if (old->release_fb) + old->release_fb->funcs->destroy(old->release_fb); + return; } @@ -6566,27 +6691,12 @@ intel_user_framebuffer_create(struct drm_device *dev, struct drm_mode_fb_cmd *mode_cmd) { struct drm_i915_gem_object *obj; - struct intel_framebuffer *intel_fb; - int ret; obj = to_intel_bo(drm_gem_object_lookup(dev, filp, mode_cmd->handle)); if (&obj->base == NULL) return ERR_PTR(-ENOENT); - intel_fb = kzalloc(sizeof(*intel_fb), GFP_KERNEL); - if (!intel_fb) { - drm_gem_object_unreference_unlocked(&obj->base); - return ERR_PTR(-ENOMEM); - } - - ret = intel_framebuffer_init(dev, intel_fb, mode_cmd, obj); - if (ret) { - drm_gem_object_unreference_unlocked(&obj->base); - kfree(intel_fb); - return ERR_PTR(ret); - } - - return &intel_fb->base; + return intel_framebuffer_create(dev, mode_cmd, obj); } static const struct drm_mode_config_funcs intel_mode_funcs = { -- cgit v1.1 From f564048e201ead4d4d02138bc60ae28f83797ac4 Mon Sep 17 00:00:00 2001 From: Eric Anholt Date: Wed, 30 Mar 2011 13:01:02 -0700 Subject: drm/i915: Split the crtc_mode_set function along HAS_PCH_SPLIT() lines. This path, which shouldn't be *that* complicated, is now so littered with per-chipset tweaks that it's hard to trace the order of what happens. HAS_PCH_SPLIT() is the most radical change across chipsets, so it seems like a natural split to simplify the code. This first commit just copies the existing code without changing anything. v2: updated to track removal of call to intel_enable_plane from i9xx_crtc_mode_set Signed-off-by: Eric Anholt Hella-acked-by: Jesse Barnes Signed-off-by: Chris Wilson --- drivers/gpu/drm/i915/intel_display.c | 681 ++++++++++++++++++++++++++++++++++- 1 file changed, 674 insertions(+), 7 deletions(-) (limited to 'drivers/gpu/drm/i915/intel_display.c') diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c index a47e5ee..b621367 100644 --- a/drivers/gpu/drm/i915/intel_display.c +++ b/drivers/gpu/drm/i915/intel_display.c @@ -4516,11 +4516,659 @@ static inline bool intel_panel_use_ssc(struct drm_i915_private *dev_priv) return dev_priv->lvds_use_ssc && i915_panel_use_ssc; } -static int intel_crtc_mode_set(struct drm_crtc *crtc, - struct drm_display_mode *mode, - struct drm_display_mode *adjusted_mode, - int x, int y, - struct drm_framebuffer *old_fb) +static int i9xx_crtc_mode_set(struct drm_crtc *crtc, + struct drm_display_mode *mode, + struct drm_display_mode *adjusted_mode, + int x, int y, + struct drm_framebuffer *old_fb) +{ + struct drm_device *dev = crtc->dev; + struct drm_i915_private *dev_priv = dev->dev_private; + struct intel_crtc *intel_crtc = to_intel_crtc(crtc); + int pipe = intel_crtc->pipe; + int plane = intel_crtc->plane; + u32 fp_reg, dpll_reg; + int refclk, num_connectors = 0; + intel_clock_t clock, reduced_clock; + u32 dpll, fp = 0, fp2 = 0, dspcntr, pipeconf; + bool ok, has_reduced_clock = false, is_sdvo = false, is_dvo = false; + bool is_crt = false, is_lvds = false, is_tv = false, is_dp = false; + struct intel_encoder *has_edp_encoder = NULL; + struct drm_mode_config *mode_config = &dev->mode_config; + struct intel_encoder *encoder; + const intel_limit_t *limit; + int ret; + struct fdi_m_n m_n = {0}; + u32 reg, temp; + u32 lvds_sync = 0; + int target_clock; + + drm_vblank_pre_modeset(dev, pipe); + + list_for_each_entry(encoder, &mode_config->encoder_list, base.head) { + if (encoder->base.crtc != crtc) + continue; + + switch (encoder->type) { + case INTEL_OUTPUT_LVDS: + is_lvds = true; + break; + case INTEL_OUTPUT_SDVO: + case INTEL_OUTPUT_HDMI: + is_sdvo = true; + if (encoder->needs_tv_clock) + is_tv = true; + break; + case INTEL_OUTPUT_DVO: + is_dvo = true; + break; + case INTEL_OUTPUT_TVOUT: + is_tv = true; + break; + case INTEL_OUTPUT_ANALOG: + is_crt = true; + break; + case INTEL_OUTPUT_DISPLAYPORT: + is_dp = true; + break; + case INTEL_OUTPUT_EDP: + has_edp_encoder = encoder; + break; + } + + num_connectors++; + } + + if (is_lvds && intel_panel_use_ssc(dev_priv) && num_connectors < 2) { + refclk = dev_priv->lvds_ssc_freq * 1000; + DRM_DEBUG_KMS("using SSC reference clock of %d MHz\n", + refclk / 1000); + } else if (!IS_GEN2(dev)) { + refclk = 96000; + if (HAS_PCH_SPLIT(dev) && + (!has_edp_encoder || intel_encoder_is_pch_edp(&has_edp_encoder->base))) + refclk = 120000; /* 120Mhz refclk */ + } else { + refclk = 48000; + } + + /* + * Returns a set of divisors for the desired target clock with the given + * refclk, or FALSE. The returned values represent the clock equation: + * reflck * (5 * (m1 + 2) + (m2 + 2)) / (n + 2) / p1 / p2. + */ + limit = intel_limit(crtc, refclk); + ok = limit->find_pll(limit, crtc, adjusted_mode->clock, refclk, &clock); + if (!ok) { + DRM_ERROR("Couldn't find PLL settings for mode!\n"); + drm_vblank_post_modeset(dev, pipe); + return -EINVAL; + } + + /* Ensure that the cursor is valid for the new mode before changing... */ + intel_crtc_update_cursor(crtc, true); + + if (is_lvds && dev_priv->lvds_downclock_avail) { + has_reduced_clock = limit->find_pll(limit, crtc, + dev_priv->lvds_downclock, + refclk, + &reduced_clock); + if (has_reduced_clock && (clock.p != reduced_clock.p)) { + /* + * If the different P is found, it means that we can't + * switch the display clock by using the FP0/FP1. + * In such case we will disable the LVDS downclock + * feature. + */ + DRM_DEBUG_KMS("Different P is found for " + "LVDS clock/downclock\n"); + has_reduced_clock = 0; + } + } + /* SDVO TV has fixed PLL values depend on its clock range, + this mirrors vbios setting. */ + if (is_sdvo && is_tv) { + if (adjusted_mode->clock >= 100000 + && adjusted_mode->clock < 140500) { + clock.p1 = 2; + clock.p2 = 10; + clock.n = 3; + clock.m1 = 16; + clock.m2 = 8; + } else if (adjusted_mode->clock >= 140500 + && adjusted_mode->clock <= 200000) { + clock.p1 = 1; + clock.p2 = 10; + clock.n = 6; + clock.m1 = 12; + clock.m2 = 8; + } + } + + /* FDI link */ + if (HAS_PCH_SPLIT(dev)) { + int pixel_multiplier = intel_mode_get_pixel_multiplier(adjusted_mode); + int lane = 0, link_bw, bpp; + /* CPU eDP doesn't require FDI link, so just set DP M/N + according to current link config */ + if (has_edp_encoder && !intel_encoder_is_pch_edp(&has_edp_encoder->base)) { + target_clock = mode->clock; + intel_edp_link_config(has_edp_encoder, + &lane, &link_bw); + } else { + /* [e]DP over FDI requires target mode clock + instead of link clock */ + if (is_dp || intel_encoder_is_pch_edp(&has_edp_encoder->base)) + target_clock = mode->clock; + else + target_clock = adjusted_mode->clock; + + /* FDI is a binary signal running at ~2.7GHz, encoding + * each output octet as 10 bits. The actual frequency + * is stored as a divider into a 100MHz clock, and the + * mode pixel clock is stored in units of 1KHz. + * Hence the bw of each lane in terms of the mode signal + * is: + */ + link_bw = intel_fdi_link_freq(dev) * MHz(100)/KHz(1)/10; + } + + /* determine panel color depth */ + temp = I915_READ(PIPECONF(pipe)); + temp &= ~PIPE_BPC_MASK; + if (is_lvds) { + /* the BPC will be 6 if it is 18-bit LVDS panel */ + if ((I915_READ(PCH_LVDS) & LVDS_A3_POWER_MASK) == LVDS_A3_POWER_UP) + temp |= PIPE_8BPC; + else + temp |= PIPE_6BPC; + } else if (has_edp_encoder) { + switch (dev_priv->edp.bpp/3) { + case 8: + temp |= PIPE_8BPC; + break; + case 10: + temp |= PIPE_10BPC; + break; + case 6: + temp |= PIPE_6BPC; + break; + case 12: + temp |= PIPE_12BPC; + break; + } + } else + temp |= PIPE_8BPC; + I915_WRITE(PIPECONF(pipe), temp); + + switch (temp & PIPE_BPC_MASK) { + case PIPE_8BPC: + bpp = 24; + break; + case PIPE_10BPC: + bpp = 30; + break; + case PIPE_6BPC: + bpp = 18; + break; + case PIPE_12BPC: + bpp = 36; + break; + default: + DRM_ERROR("unknown pipe bpc value\n"); + bpp = 24; + } + + if (!lane) { + /* + * Account for spread spectrum to avoid + * oversubscribing the link. Max center spread + * is 2.5%; use 5% for safety's sake. + */ + u32 bps = target_clock * bpp * 21 / 20; + lane = bps / (link_bw * 8) + 1; + } + + intel_crtc->fdi_lanes = lane; + + if (pixel_multiplier > 1) + link_bw *= pixel_multiplier; + ironlake_compute_m_n(bpp, lane, target_clock, link_bw, &m_n); + } + + /* Ironlake: try to setup display ref clock before DPLL + * enabling. This is only under driver's control after + * PCH B stepping, previous chipset stepping should be + * ignoring this setting. + */ + if (HAS_PCH_SPLIT(dev)) { + temp = I915_READ(PCH_DREF_CONTROL); + /* Always enable nonspread source */ + temp &= ~DREF_NONSPREAD_SOURCE_MASK; + temp |= DREF_NONSPREAD_SOURCE_ENABLE; + temp &= ~DREF_SSC_SOURCE_MASK; + temp |= DREF_SSC_SOURCE_ENABLE; + I915_WRITE(PCH_DREF_CONTROL, temp); + + POSTING_READ(PCH_DREF_CONTROL); + udelay(200); + + if (has_edp_encoder) { + if (intel_panel_use_ssc(dev_priv)) { + temp |= DREF_SSC1_ENABLE; + I915_WRITE(PCH_DREF_CONTROL, temp); + + POSTING_READ(PCH_DREF_CONTROL); + udelay(200); + } + temp &= ~DREF_CPU_SOURCE_OUTPUT_MASK; + + /* Enable CPU source on CPU attached eDP */ + if (!intel_encoder_is_pch_edp(&has_edp_encoder->base)) { + if (intel_panel_use_ssc(dev_priv)) + temp |= DREF_CPU_SOURCE_OUTPUT_DOWNSPREAD; + else + temp |= DREF_CPU_SOURCE_OUTPUT_NONSPREAD; + } else { + /* Enable SSC on PCH eDP if needed */ + if (intel_panel_use_ssc(dev_priv)) { + DRM_ERROR("enabling SSC on PCH\n"); + temp |= DREF_SUPERSPREAD_SOURCE_ENABLE; + } + } + I915_WRITE(PCH_DREF_CONTROL, temp); + POSTING_READ(PCH_DREF_CONTROL); + udelay(200); + } + } + + if (IS_PINEVIEW(dev)) { + fp = (1 << clock.n) << 16 | clock.m1 << 8 | clock.m2; + if (has_reduced_clock) + fp2 = (1 << reduced_clock.n) << 16 | + reduced_clock.m1 << 8 | reduced_clock.m2; + } else { + fp = clock.n << 16 | clock.m1 << 8 | clock.m2; + if (has_reduced_clock) + fp2 = reduced_clock.n << 16 | reduced_clock.m1 << 8 | + reduced_clock.m2; + } + + /* Enable autotuning of the PLL clock (if permissible) */ + if (HAS_PCH_SPLIT(dev)) { + int factor = 21; + + if (is_lvds) { + if ((intel_panel_use_ssc(dev_priv) && + dev_priv->lvds_ssc_freq == 100) || + (I915_READ(PCH_LVDS) & LVDS_CLKB_POWER_MASK) == LVDS_CLKB_POWER_UP) + factor = 25; + } else if (is_sdvo && is_tv) + factor = 20; + + if (clock.m1 < factor * clock.n) + fp |= FP_CB_TUNE; + } + + dpll = 0; + if (!HAS_PCH_SPLIT(dev)) + dpll = DPLL_VGA_MODE_DIS; + + if (!IS_GEN2(dev)) { + if (is_lvds) + dpll |= DPLLB_MODE_LVDS; + else + dpll |= DPLLB_MODE_DAC_SERIAL; + if (is_sdvo) { + int pixel_multiplier = intel_mode_get_pixel_multiplier(adjusted_mode); + if (pixel_multiplier > 1) { + if (IS_I945G(dev) || IS_I945GM(dev) || IS_G33(dev)) + dpll |= (pixel_multiplier - 1) << SDVO_MULTIPLIER_SHIFT_HIRES; + else if (HAS_PCH_SPLIT(dev)) + dpll |= (pixel_multiplier - 1) << PLL_REF_SDVO_HDMI_MULTIPLIER_SHIFT; + } + dpll |= DPLL_DVO_HIGH_SPEED; + } + if (is_dp || intel_encoder_is_pch_edp(&has_edp_encoder->base)) + dpll |= DPLL_DVO_HIGH_SPEED; + + /* compute bitmask from p1 value */ + if (IS_PINEVIEW(dev)) + dpll |= (1 << (clock.p1 - 1)) << DPLL_FPA01_P1_POST_DIV_SHIFT_PINEVIEW; + else { + dpll |= (1 << (clock.p1 - 1)) << DPLL_FPA01_P1_POST_DIV_SHIFT; + /* also FPA1 */ + if (HAS_PCH_SPLIT(dev)) + dpll |= (1 << (clock.p1 - 1)) << DPLL_FPA1_P1_POST_DIV_SHIFT; + if (IS_G4X(dev) && has_reduced_clock) + dpll |= (1 << (reduced_clock.p1 - 1)) << DPLL_FPA1_P1_POST_DIV_SHIFT; + } + switch (clock.p2) { + case 5: + dpll |= DPLL_DAC_SERIAL_P2_CLOCK_DIV_5; + break; + case 7: + dpll |= DPLLB_LVDS_P2_CLOCK_DIV_7; + break; + case 10: + dpll |= DPLL_DAC_SERIAL_P2_CLOCK_DIV_10; + break; + case 14: + dpll |= DPLLB_LVDS_P2_CLOCK_DIV_14; + break; + } + if (INTEL_INFO(dev)->gen >= 4 && !HAS_PCH_SPLIT(dev)) + dpll |= (6 << PLL_LOAD_PULSE_PHASE_SHIFT); + } else { + if (is_lvds) { + dpll |= (1 << (clock.p1 - 1)) << DPLL_FPA01_P1_POST_DIV_SHIFT; + } else { + if (clock.p1 == 2) + dpll |= PLL_P1_DIVIDE_BY_TWO; + else + dpll |= (clock.p1 - 2) << DPLL_FPA01_P1_POST_DIV_SHIFT; + if (clock.p2 == 4) + dpll |= PLL_P2_DIVIDE_BY_4; + } + } + + if (is_sdvo && is_tv) + dpll |= PLL_REF_INPUT_TVCLKINBC; + else if (is_tv) + /* XXX: just matching BIOS for now */ + /* dpll |= PLL_REF_INPUT_TVCLKINBC; */ + dpll |= 3; + else if (is_lvds && intel_panel_use_ssc(dev_priv) && num_connectors < 2) + dpll |= PLLB_REF_INPUT_SPREADSPECTRUMIN; + else + dpll |= PLL_REF_INPUT_DREFCLK; + + /* setup pipeconf */ + pipeconf = I915_READ(PIPECONF(pipe)); + + /* Set up the display plane register */ + dspcntr = DISPPLANE_GAMMA_ENABLE; + + /* Ironlake's plane is forced to pipe, bit 24 is to + enable color space conversion */ + if (!HAS_PCH_SPLIT(dev)) { + if (pipe == 0) + dspcntr &= ~DISPPLANE_SEL_PIPE_MASK; + else + dspcntr |= DISPPLANE_SEL_PIPE_B; + } + + if (pipe == 0 && INTEL_INFO(dev)->gen < 4) { + /* Enable pixel doubling when the dot clock is > 90% of the (display) + * core speed. + * + * XXX: No double-wide on 915GM pipe B. Is that the only reason for the + * pipe == 0 check? + */ + if (mode->clock > + dev_priv->display.get_display_clock_speed(dev) * 9 / 10) + pipeconf |= PIPECONF_DOUBLE_WIDE; + else + pipeconf &= ~PIPECONF_DOUBLE_WIDE; + } + + if (!HAS_PCH_SPLIT(dev)) + dpll |= DPLL_VCO_ENABLE; + + DRM_DEBUG_KMS("Mode for pipe %c:\n", pipe == 0 ? 'A' : 'B'); + drm_mode_debug_printmodeline(mode); + + /* assign to Ironlake registers */ + if (HAS_PCH_SPLIT(dev)) { + fp_reg = PCH_FP0(pipe); + dpll_reg = PCH_DPLL(pipe); + } else { + fp_reg = FP0(pipe); + dpll_reg = DPLL(pipe); + } + + /* PCH eDP needs FDI, but CPU eDP does not */ + if (!has_edp_encoder || intel_encoder_is_pch_edp(&has_edp_encoder->base)) { + I915_WRITE(fp_reg, fp); + I915_WRITE(dpll_reg, dpll & ~DPLL_VCO_ENABLE); + + POSTING_READ(dpll_reg); + udelay(150); + } + + /* enable transcoder DPLL */ + if (HAS_PCH_CPT(dev)) { + temp = I915_READ(PCH_DPLL_SEL); + switch (pipe) { + case 0: + temp |= TRANSA_DPLL_ENABLE | TRANSA_DPLLA_SEL; + break; + case 1: + temp |= TRANSB_DPLL_ENABLE | TRANSB_DPLLB_SEL; + break; + case 2: + /* FIXME: manage transcoder PLLs? */ + temp |= TRANSC_DPLL_ENABLE | TRANSC_DPLLB_SEL; + break; + default: + BUG(); + } + I915_WRITE(PCH_DPLL_SEL, temp); + + POSTING_READ(PCH_DPLL_SEL); + udelay(150); + } + + /* The LVDS pin pair needs to be on before the DPLLs are enabled. + * This is an exception to the general rule that mode_set doesn't turn + * things on. + */ + if (is_lvds) { + reg = LVDS; + if (HAS_PCH_SPLIT(dev)) + reg = PCH_LVDS; + + temp = I915_READ(reg); + temp |= LVDS_PORT_EN | LVDS_A0A2_CLKA_POWER_UP; + if (pipe == 1) { + if (HAS_PCH_CPT(dev)) + temp |= PORT_TRANS_B_SEL_CPT; + else + temp |= LVDS_PIPEB_SELECT; + } else { + if (HAS_PCH_CPT(dev)) + temp &= ~PORT_TRANS_SEL_MASK; + else + temp &= ~LVDS_PIPEB_SELECT; + } + /* set the corresponsding LVDS_BORDER bit */ + temp |= dev_priv->lvds_border_bits; + /* Set the B0-B3 data pairs corresponding to whether we're going to + * set the DPLLs for dual-channel mode or not. + */ + if (clock.p2 == 7) + temp |= LVDS_B0B3_POWER_UP | LVDS_CLKB_POWER_UP; + else + temp &= ~(LVDS_B0B3_POWER_UP | LVDS_CLKB_POWER_UP); + + /* It would be nice to set 24 vs 18-bit mode (LVDS_A3_POWER_UP) + * appropriately here, but we need to look more thoroughly into how + * panels behave in the two modes. + */ + /* set the dithering flag on non-PCH LVDS as needed */ + if (INTEL_INFO(dev)->gen >= 4 && !HAS_PCH_SPLIT(dev)) { + if (dev_priv->lvds_dither) + temp |= LVDS_ENABLE_DITHER; + else + temp &= ~LVDS_ENABLE_DITHER; + } + if (adjusted_mode->flags & DRM_MODE_FLAG_NHSYNC) + lvds_sync |= LVDS_HSYNC_POLARITY; + if (adjusted_mode->flags & DRM_MODE_FLAG_NVSYNC) + lvds_sync |= LVDS_VSYNC_POLARITY; + if ((temp & (LVDS_HSYNC_POLARITY | LVDS_VSYNC_POLARITY)) + != lvds_sync) { + char flags[2] = "-+"; + DRM_INFO("Changing LVDS panel from " + "(%chsync, %cvsync) to (%chsync, %cvsync)\n", + flags[!(temp & LVDS_HSYNC_POLARITY)], + flags[!(temp & LVDS_VSYNC_POLARITY)], + flags[!(lvds_sync & LVDS_HSYNC_POLARITY)], + flags[!(lvds_sync & LVDS_VSYNC_POLARITY)]); + temp &= ~(LVDS_HSYNC_POLARITY | LVDS_VSYNC_POLARITY); + temp |= lvds_sync; + } + I915_WRITE(reg, temp); + } + + /* set the dithering flag and clear for anything other than a panel. */ + if (HAS_PCH_SPLIT(dev)) { + pipeconf &= ~PIPECONF_DITHER_EN; + pipeconf &= ~PIPECONF_DITHER_TYPE_MASK; + if (dev_priv->lvds_dither && (is_lvds || has_edp_encoder)) { + pipeconf |= PIPECONF_DITHER_EN; + pipeconf |= PIPECONF_DITHER_TYPE_ST1; + } + } + + if (is_dp || intel_encoder_is_pch_edp(&has_edp_encoder->base)) { + intel_dp_set_m_n(crtc, mode, adjusted_mode); + } else if (HAS_PCH_SPLIT(dev)) { + /* For non-DP output, clear any trans DP clock recovery setting.*/ + I915_WRITE(TRANSDATA_M1(pipe), 0); + I915_WRITE(TRANSDATA_N1(pipe), 0); + I915_WRITE(TRANSDPLINK_M1(pipe), 0); + I915_WRITE(TRANSDPLINK_N1(pipe), 0); + } + + if (!has_edp_encoder || intel_encoder_is_pch_edp(&has_edp_encoder->base)) { + I915_WRITE(dpll_reg, dpll); + + /* Wait for the clocks to stabilize. */ + POSTING_READ(dpll_reg); + udelay(150); + + if (INTEL_INFO(dev)->gen >= 4 && !HAS_PCH_SPLIT(dev)) { + temp = 0; + if (is_sdvo) { + temp = intel_mode_get_pixel_multiplier(adjusted_mode); + if (temp > 1) + temp = (temp - 1) << DPLL_MD_UDI_MULTIPLIER_SHIFT; + else + temp = 0; + } + I915_WRITE(DPLL_MD(pipe), temp); + } else { + /* The pixel multiplier can only be updated once the + * DPLL is enabled and the clocks are stable. + * + * So write it again. + */ + I915_WRITE(dpll_reg, dpll); + } + } + + intel_crtc->lowfreq_avail = false; + if (is_lvds && has_reduced_clock && i915_powersave) { + I915_WRITE(fp_reg + 4, fp2); + intel_crtc->lowfreq_avail = true; + if (HAS_PIPE_CXSR(dev)) { + DRM_DEBUG_KMS("enabling CxSR downclocking\n"); + pipeconf |= PIPECONF_CXSR_DOWNCLOCK; + } + } else { + I915_WRITE(fp_reg + 4, fp); + if (HAS_PIPE_CXSR(dev)) { + DRM_DEBUG_KMS("disabling CxSR downclocking\n"); + pipeconf &= ~PIPECONF_CXSR_DOWNCLOCK; + } + } + + if (adjusted_mode->flags & DRM_MODE_FLAG_INTERLACE) { + pipeconf |= PIPECONF_INTERLACE_W_FIELD_INDICATION; + /* the chip adds 2 halflines automatically */ + adjusted_mode->crtc_vdisplay -= 1; + adjusted_mode->crtc_vtotal -= 1; + adjusted_mode->crtc_vblank_start -= 1; + adjusted_mode->crtc_vblank_end -= 1; + adjusted_mode->crtc_vsync_end -= 1; + adjusted_mode->crtc_vsync_start -= 1; + } else + pipeconf &= ~PIPECONF_INTERLACE_W_FIELD_INDICATION; /* progressive */ + + I915_WRITE(HTOTAL(pipe), + (adjusted_mode->crtc_hdisplay - 1) | + ((adjusted_mode->crtc_htotal - 1) << 16)); + I915_WRITE(HBLANK(pipe), + (adjusted_mode->crtc_hblank_start - 1) | + ((adjusted_mode->crtc_hblank_end - 1) << 16)); + I915_WRITE(HSYNC(pipe), + (adjusted_mode->crtc_hsync_start - 1) | + ((adjusted_mode->crtc_hsync_end - 1) << 16)); + + I915_WRITE(VTOTAL(pipe), + (adjusted_mode->crtc_vdisplay - 1) | + ((adjusted_mode->crtc_vtotal - 1) << 16)); + I915_WRITE(VBLANK(pipe), + (adjusted_mode->crtc_vblank_start - 1) | + ((adjusted_mode->crtc_vblank_end - 1) << 16)); + I915_WRITE(VSYNC(pipe), + (adjusted_mode->crtc_vsync_start - 1) | + ((adjusted_mode->crtc_vsync_end - 1) << 16)); + + /* pipesrc and dspsize control the size that is scaled from, + * which should always be the user's requested size. + */ + if (!HAS_PCH_SPLIT(dev)) { + I915_WRITE(DSPSIZE(plane), + ((mode->vdisplay - 1) << 16) | + (mode->hdisplay - 1)); + I915_WRITE(DSPPOS(plane), 0); + } + I915_WRITE(PIPESRC(pipe), + ((mode->hdisplay - 1) << 16) | (mode->vdisplay - 1)); + + if (HAS_PCH_SPLIT(dev)) { + I915_WRITE(PIPE_DATA_M1(pipe), TU_SIZE(m_n.tu) | m_n.gmch_m); + I915_WRITE(PIPE_DATA_N1(pipe), m_n.gmch_n); + I915_WRITE(PIPE_LINK_M1(pipe), m_n.link_m); + I915_WRITE(PIPE_LINK_N1(pipe), m_n.link_n); + + if (has_edp_encoder && !intel_encoder_is_pch_edp(&has_edp_encoder->base)) { + ironlake_set_pll_edp(crtc, adjusted_mode->clock); + } + } + + I915_WRITE(PIPECONF(pipe), pipeconf); + POSTING_READ(PIPECONF(pipe)); + if (!HAS_PCH_SPLIT(dev)) + intel_enable_pipe(dev_priv, pipe, false); + + intel_wait_for_vblank(dev, pipe); + + if (IS_GEN5(dev)) { + /* enable address swizzle for tiling buffer */ + temp = I915_READ(DISP_ARB_CTL); + I915_WRITE(DISP_ARB_CTL, temp | DISP_TILE_SURFACE_SWIZZLING); + } + + I915_WRITE(DSPCNTR(plane), dspcntr); + POSTING_READ(DSPCNTR(plane)); + + ret = intel_pipe_set_base(crtc, x, y, old_fb); + + intel_update_watermarks(dev); + + drm_vblank_post_modeset(dev, pipe); + + return ret; +} + +static int ironlake_crtc_mode_set(struct drm_crtc *crtc, + struct drm_display_mode *mode, + struct drm_display_mode *adjusted_mode, + int x, int y, + struct drm_framebuffer *old_fb) { struct drm_device *dev = crtc->dev; struct drm_i915_private *dev_priv = dev->dev_private; @@ -5164,6 +5812,22 @@ static int intel_crtc_mode_set(struct drm_crtc *crtc, return ret; } +static int intel_crtc_mode_set(struct drm_crtc *crtc, + struct drm_display_mode *mode, + struct drm_display_mode *adjusted_mode, + int x, int y, + struct drm_framebuffer *old_fb) +{ + struct drm_device *dev = crtc->dev; + struct drm_i915_private *dev_priv = dev->dev_private; + int ret; + + ret = dev_priv->display.crtc_mode_set(crtc, mode, adjusted_mode, + x, y, old_fb); + + return ret; +} + /** Loads the palette/gamma unit for the CRTC with the prepared values */ void intel_crtc_load_lut(struct drm_crtc *crtc) { @@ -7329,10 +7993,13 @@ static void intel_init_display(struct drm_device *dev) struct drm_i915_private *dev_priv = dev->dev_private; /* We always want a DPMS function */ - if (HAS_PCH_SPLIT(dev)) + if (HAS_PCH_SPLIT(dev)) { dev_priv->display.dpms = ironlake_crtc_dpms; - else + dev_priv->display.crtc_mode_set = ironlake_crtc_mode_set; + } else { dev_priv->display.dpms = i9xx_crtc_dpms; + dev_priv->display.crtc_mode_set = i9xx_crtc_mode_set; + } if (I915_HAS_FBC(dev)) { if (HAS_PCH_SPLIT(dev)) { -- cgit v1.1 From 0b701d27b37d52b80d8da2d8d15fb99e072ee819 Mon Sep 17 00:00:00 2001 From: Eric Anholt Date: Wed, 30 Mar 2011 13:01:03 -0700 Subject: drm/i915: Move the vblank pre/post modeset to the common crtc_mode_set. Signed-off-by: Eric Anholt Reviewed-by: Jesse Barnes Signed-off-by: Chris Wilson --- drivers/gpu/drm/i915/intel_display.c | 16 ++++++---------- 1 file changed, 6 insertions(+), 10 deletions(-) (limited to 'drivers/gpu/drm/i915/intel_display.c') diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c index b621367..f121aaf 100644 --- a/drivers/gpu/drm/i915/intel_display.c +++ b/drivers/gpu/drm/i915/intel_display.c @@ -4543,8 +4543,6 @@ static int i9xx_crtc_mode_set(struct drm_crtc *crtc, u32 lvds_sync = 0; int target_clock; - drm_vblank_pre_modeset(dev, pipe); - list_for_each_entry(encoder, &mode_config->encoder_list, base.head) { if (encoder->base.crtc != crtc) continue; @@ -4601,7 +4599,6 @@ static int i9xx_crtc_mode_set(struct drm_crtc *crtc, ok = limit->find_pll(limit, crtc, adjusted_mode->clock, refclk, &clock); if (!ok) { DRM_ERROR("Couldn't find PLL settings for mode!\n"); - drm_vblank_post_modeset(dev, pipe); return -EINVAL; } @@ -5159,8 +5156,6 @@ static int i9xx_crtc_mode_set(struct drm_crtc *crtc, intel_update_watermarks(dev); - drm_vblank_post_modeset(dev, pipe); - return ret; } @@ -5191,8 +5186,6 @@ static int ironlake_crtc_mode_set(struct drm_crtc *crtc, u32 lvds_sync = 0; int target_clock; - drm_vblank_pre_modeset(dev, pipe); - list_for_each_entry(encoder, &mode_config->encoder_list, base.head) { if (encoder->base.crtc != crtc) continue; @@ -5249,7 +5242,6 @@ static int ironlake_crtc_mode_set(struct drm_crtc *crtc, ok = limit->find_pll(limit, crtc, adjusted_mode->clock, refclk, &clock); if (!ok) { DRM_ERROR("Couldn't find PLL settings for mode!\n"); - drm_vblank_post_modeset(dev, pipe); return -EINVAL; } @@ -5807,8 +5799,6 @@ static int ironlake_crtc_mode_set(struct drm_crtc *crtc, intel_update_watermarks(dev); - drm_vblank_post_modeset(dev, pipe); - return ret; } @@ -5820,11 +5810,17 @@ static int intel_crtc_mode_set(struct drm_crtc *crtc, { struct drm_device *dev = crtc->dev; struct drm_i915_private *dev_priv = dev->dev_private; + struct intel_crtc *intel_crtc = to_intel_crtc(crtc); + int pipe = intel_crtc->pipe; int ret; + drm_vblank_pre_modeset(dev, pipe); + ret = dev_priv->display.crtc_mode_set(crtc, mode, adjusted_mode, x, y, old_fb); + drm_vblank_post_modeset(dev, pipe); + return ret; } -- cgit v1.1 From 929c77fb38aa1e5f028f1b59dfb641b25fffea8b Mon Sep 17 00:00:00 2001 From: Eric Anholt Date: Wed, 30 Mar 2011 13:01:04 -0700 Subject: drm/i915: Remove the PCH paths from the pre-Ironlake crtc_mode_set(). Signed-off-by: Eric Anholt Reviewed-by: Jesse Barnes --- drivers/gpu/drm/i915/intel_display.c | 281 +++-------------------------------- 1 file changed, 23 insertions(+), 258 deletions(-) (limited to 'drivers/gpu/drm/i915/intel_display.c') diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c index f121aaf..622820b 100644 --- a/drivers/gpu/drm/i915/intel_display.c +++ b/drivers/gpu/drm/i915/intel_display.c @@ -4538,10 +4538,8 @@ static int i9xx_crtc_mode_set(struct drm_crtc *crtc, struct intel_encoder *encoder; const intel_limit_t *limit; int ret; - struct fdi_m_n m_n = {0}; u32 reg, temp; u32 lvds_sync = 0; - int target_clock; list_for_each_entry(encoder, &mode_config->encoder_list, base.head) { if (encoder->base.crtc != crtc) @@ -4583,9 +4581,6 @@ static int i9xx_crtc_mode_set(struct drm_crtc *crtc, refclk / 1000); } else if (!IS_GEN2(dev)) { refclk = 96000; - if (HAS_PCH_SPLIT(dev) && - (!has_edp_encoder || intel_encoder_is_pch_edp(&has_edp_encoder->base))) - refclk = 120000; /* 120Mhz refclk */ } else { refclk = 48000; } @@ -4642,143 +4637,6 @@ static int i9xx_crtc_mode_set(struct drm_crtc *crtc, } } - /* FDI link */ - if (HAS_PCH_SPLIT(dev)) { - int pixel_multiplier = intel_mode_get_pixel_multiplier(adjusted_mode); - int lane = 0, link_bw, bpp; - /* CPU eDP doesn't require FDI link, so just set DP M/N - according to current link config */ - if (has_edp_encoder && !intel_encoder_is_pch_edp(&has_edp_encoder->base)) { - target_clock = mode->clock; - intel_edp_link_config(has_edp_encoder, - &lane, &link_bw); - } else { - /* [e]DP over FDI requires target mode clock - instead of link clock */ - if (is_dp || intel_encoder_is_pch_edp(&has_edp_encoder->base)) - target_clock = mode->clock; - else - target_clock = adjusted_mode->clock; - - /* FDI is a binary signal running at ~2.7GHz, encoding - * each output octet as 10 bits. The actual frequency - * is stored as a divider into a 100MHz clock, and the - * mode pixel clock is stored in units of 1KHz. - * Hence the bw of each lane in terms of the mode signal - * is: - */ - link_bw = intel_fdi_link_freq(dev) * MHz(100)/KHz(1)/10; - } - - /* determine panel color depth */ - temp = I915_READ(PIPECONF(pipe)); - temp &= ~PIPE_BPC_MASK; - if (is_lvds) { - /* the BPC will be 6 if it is 18-bit LVDS panel */ - if ((I915_READ(PCH_LVDS) & LVDS_A3_POWER_MASK) == LVDS_A3_POWER_UP) - temp |= PIPE_8BPC; - else - temp |= PIPE_6BPC; - } else if (has_edp_encoder) { - switch (dev_priv->edp.bpp/3) { - case 8: - temp |= PIPE_8BPC; - break; - case 10: - temp |= PIPE_10BPC; - break; - case 6: - temp |= PIPE_6BPC; - break; - case 12: - temp |= PIPE_12BPC; - break; - } - } else - temp |= PIPE_8BPC; - I915_WRITE(PIPECONF(pipe), temp); - - switch (temp & PIPE_BPC_MASK) { - case PIPE_8BPC: - bpp = 24; - break; - case PIPE_10BPC: - bpp = 30; - break; - case PIPE_6BPC: - bpp = 18; - break; - case PIPE_12BPC: - bpp = 36; - break; - default: - DRM_ERROR("unknown pipe bpc value\n"); - bpp = 24; - } - - if (!lane) { - /* - * Account for spread spectrum to avoid - * oversubscribing the link. Max center spread - * is 2.5%; use 5% for safety's sake. - */ - u32 bps = target_clock * bpp * 21 / 20; - lane = bps / (link_bw * 8) + 1; - } - - intel_crtc->fdi_lanes = lane; - - if (pixel_multiplier > 1) - link_bw *= pixel_multiplier; - ironlake_compute_m_n(bpp, lane, target_clock, link_bw, &m_n); - } - - /* Ironlake: try to setup display ref clock before DPLL - * enabling. This is only under driver's control after - * PCH B stepping, previous chipset stepping should be - * ignoring this setting. - */ - if (HAS_PCH_SPLIT(dev)) { - temp = I915_READ(PCH_DREF_CONTROL); - /* Always enable nonspread source */ - temp &= ~DREF_NONSPREAD_SOURCE_MASK; - temp |= DREF_NONSPREAD_SOURCE_ENABLE; - temp &= ~DREF_SSC_SOURCE_MASK; - temp |= DREF_SSC_SOURCE_ENABLE; - I915_WRITE(PCH_DREF_CONTROL, temp); - - POSTING_READ(PCH_DREF_CONTROL); - udelay(200); - - if (has_edp_encoder) { - if (intel_panel_use_ssc(dev_priv)) { - temp |= DREF_SSC1_ENABLE; - I915_WRITE(PCH_DREF_CONTROL, temp); - - POSTING_READ(PCH_DREF_CONTROL); - udelay(200); - } - temp &= ~DREF_CPU_SOURCE_OUTPUT_MASK; - - /* Enable CPU source on CPU attached eDP */ - if (!intel_encoder_is_pch_edp(&has_edp_encoder->base)) { - if (intel_panel_use_ssc(dev_priv)) - temp |= DREF_CPU_SOURCE_OUTPUT_DOWNSPREAD; - else - temp |= DREF_CPU_SOURCE_OUTPUT_NONSPREAD; - } else { - /* Enable SSC on PCH eDP if needed */ - if (intel_panel_use_ssc(dev_priv)) { - DRM_ERROR("enabling SSC on PCH\n"); - temp |= DREF_SUPERSPREAD_SOURCE_ENABLE; - } - } - I915_WRITE(PCH_DREF_CONTROL, temp); - POSTING_READ(PCH_DREF_CONTROL); - udelay(200); - } - } - if (IS_PINEVIEW(dev)) { fp = (1 << clock.n) << 16 | clock.m1 << 8 | clock.m2; if (has_reduced_clock) @@ -4791,25 +4649,7 @@ static int i9xx_crtc_mode_set(struct drm_crtc *crtc, reduced_clock.m2; } - /* Enable autotuning of the PLL clock (if permissible) */ - if (HAS_PCH_SPLIT(dev)) { - int factor = 21; - - if (is_lvds) { - if ((intel_panel_use_ssc(dev_priv) && - dev_priv->lvds_ssc_freq == 100) || - (I915_READ(PCH_LVDS) & LVDS_CLKB_POWER_MASK) == LVDS_CLKB_POWER_UP) - factor = 25; - } else if (is_sdvo && is_tv) - factor = 20; - - if (clock.m1 < factor * clock.n) - fp |= FP_CB_TUNE; - } - - dpll = 0; - if (!HAS_PCH_SPLIT(dev)) - dpll = DPLL_VGA_MODE_DIS; + dpll = DPLL_VGA_MODE_DIS; if (!IS_GEN2(dev)) { if (is_lvds) @@ -4821,12 +4661,10 @@ static int i9xx_crtc_mode_set(struct drm_crtc *crtc, if (pixel_multiplier > 1) { if (IS_I945G(dev) || IS_I945GM(dev) || IS_G33(dev)) dpll |= (pixel_multiplier - 1) << SDVO_MULTIPLIER_SHIFT_HIRES; - else if (HAS_PCH_SPLIT(dev)) - dpll |= (pixel_multiplier - 1) << PLL_REF_SDVO_HDMI_MULTIPLIER_SHIFT; } dpll |= DPLL_DVO_HIGH_SPEED; } - if (is_dp || intel_encoder_is_pch_edp(&has_edp_encoder->base)) + if (is_dp) dpll |= DPLL_DVO_HIGH_SPEED; /* compute bitmask from p1 value */ @@ -4834,9 +4672,6 @@ static int i9xx_crtc_mode_set(struct drm_crtc *crtc, dpll |= (1 << (clock.p1 - 1)) << DPLL_FPA01_P1_POST_DIV_SHIFT_PINEVIEW; else { dpll |= (1 << (clock.p1 - 1)) << DPLL_FPA01_P1_POST_DIV_SHIFT; - /* also FPA1 */ - if (HAS_PCH_SPLIT(dev)) - dpll |= (1 << (clock.p1 - 1)) << DPLL_FPA1_P1_POST_DIV_SHIFT; if (IS_G4X(dev) && has_reduced_clock) dpll |= (1 << (reduced_clock.p1 - 1)) << DPLL_FPA1_P1_POST_DIV_SHIFT; } @@ -4854,7 +4689,7 @@ static int i9xx_crtc_mode_set(struct drm_crtc *crtc, dpll |= DPLLB_LVDS_P2_CLOCK_DIV_14; break; } - if (INTEL_INFO(dev)->gen >= 4 && !HAS_PCH_SPLIT(dev)) + if (INTEL_INFO(dev)->gen >= 4) dpll |= (6 << PLL_LOAD_PULSE_PHASE_SHIFT); } else { if (is_lvds) { @@ -4888,12 +4723,10 @@ static int i9xx_crtc_mode_set(struct drm_crtc *crtc, /* Ironlake's plane is forced to pipe, bit 24 is to enable color space conversion */ - if (!HAS_PCH_SPLIT(dev)) { - if (pipe == 0) - dspcntr &= ~DISPPLANE_SEL_PIPE_MASK; - else - dspcntr |= DISPPLANE_SEL_PIPE_B; - } + if (pipe == 0) + dspcntr &= ~DISPPLANE_SEL_PIPE_MASK; + else + dspcntr |= DISPPLANE_SEL_PIPE_B; if (pipe == 0 && INTEL_INFO(dev)->gen < 4) { /* Enable pixel doubling when the dot clock is > 90% of the (display) @@ -4909,23 +4742,16 @@ static int i9xx_crtc_mode_set(struct drm_crtc *crtc, pipeconf &= ~PIPECONF_DOUBLE_WIDE; } - if (!HAS_PCH_SPLIT(dev)) - dpll |= DPLL_VCO_ENABLE; + dpll |= DPLL_VCO_ENABLE; DRM_DEBUG_KMS("Mode for pipe %c:\n", pipe == 0 ? 'A' : 'B'); drm_mode_debug_printmodeline(mode); - /* assign to Ironlake registers */ - if (HAS_PCH_SPLIT(dev)) { - fp_reg = PCH_FP0(pipe); - dpll_reg = PCH_DPLL(pipe); - } else { - fp_reg = FP0(pipe); - dpll_reg = DPLL(pipe); - } + fp_reg = FP0(pipe); + dpll_reg = DPLL(pipe); /* PCH eDP needs FDI, but CPU eDP does not */ - if (!has_edp_encoder || intel_encoder_is_pch_edp(&has_edp_encoder->base)) { + if (!has_edp_encoder) { I915_WRITE(fp_reg, fp); I915_WRITE(dpll_reg, dpll & ~DPLL_VCO_ENABLE); @@ -4933,50 +4759,19 @@ static int i9xx_crtc_mode_set(struct drm_crtc *crtc, udelay(150); } - /* enable transcoder DPLL */ - if (HAS_PCH_CPT(dev)) { - temp = I915_READ(PCH_DPLL_SEL); - switch (pipe) { - case 0: - temp |= TRANSA_DPLL_ENABLE | TRANSA_DPLLA_SEL; - break; - case 1: - temp |= TRANSB_DPLL_ENABLE | TRANSB_DPLLB_SEL; - break; - case 2: - /* FIXME: manage transcoder PLLs? */ - temp |= TRANSC_DPLL_ENABLE | TRANSC_DPLLB_SEL; - break; - default: - BUG(); - } - I915_WRITE(PCH_DPLL_SEL, temp); - - POSTING_READ(PCH_DPLL_SEL); - udelay(150); - } - /* The LVDS pin pair needs to be on before the DPLLs are enabled. * This is an exception to the general rule that mode_set doesn't turn * things on. */ if (is_lvds) { reg = LVDS; - if (HAS_PCH_SPLIT(dev)) - reg = PCH_LVDS; temp = I915_READ(reg); temp |= LVDS_PORT_EN | LVDS_A0A2_CLKA_POWER_UP; if (pipe == 1) { - if (HAS_PCH_CPT(dev)) - temp |= PORT_TRANS_B_SEL_CPT; - else - temp |= LVDS_PIPEB_SELECT; + temp |= LVDS_PIPEB_SELECT; } else { - if (HAS_PCH_CPT(dev)) - temp &= ~PORT_TRANS_SEL_MASK; - else - temp &= ~LVDS_PIPEB_SELECT; + temp &= ~LVDS_PIPEB_SELECT; } /* set the corresponsding LVDS_BORDER bit */ temp |= dev_priv->lvds_border_bits; @@ -4992,8 +4787,8 @@ static int i9xx_crtc_mode_set(struct drm_crtc *crtc, * appropriately here, but we need to look more thoroughly into how * panels behave in the two modes. */ - /* set the dithering flag on non-PCH LVDS as needed */ - if (INTEL_INFO(dev)->gen >= 4 && !HAS_PCH_SPLIT(dev)) { + /* set the dithering flag on LVDS as needed */ + if (INTEL_INFO(dev)->gen >= 4) { if (dev_priv->lvds_dither) temp |= LVDS_ENABLE_DITHER; else @@ -5018,34 +4813,18 @@ static int i9xx_crtc_mode_set(struct drm_crtc *crtc, I915_WRITE(reg, temp); } - /* set the dithering flag and clear for anything other than a panel. */ - if (HAS_PCH_SPLIT(dev)) { - pipeconf &= ~PIPECONF_DITHER_EN; - pipeconf &= ~PIPECONF_DITHER_TYPE_MASK; - if (dev_priv->lvds_dither && (is_lvds || has_edp_encoder)) { - pipeconf |= PIPECONF_DITHER_EN; - pipeconf |= PIPECONF_DITHER_TYPE_ST1; - } - } - - if (is_dp || intel_encoder_is_pch_edp(&has_edp_encoder->base)) { + if (is_dp) { intel_dp_set_m_n(crtc, mode, adjusted_mode); - } else if (HAS_PCH_SPLIT(dev)) { - /* For non-DP output, clear any trans DP clock recovery setting.*/ - I915_WRITE(TRANSDATA_M1(pipe), 0); - I915_WRITE(TRANSDATA_N1(pipe), 0); - I915_WRITE(TRANSDPLINK_M1(pipe), 0); - I915_WRITE(TRANSDPLINK_N1(pipe), 0); } - if (!has_edp_encoder || intel_encoder_is_pch_edp(&has_edp_encoder->base)) { + if (!has_edp_encoder) { I915_WRITE(dpll_reg, dpll); /* Wait for the clocks to stabilize. */ POSTING_READ(dpll_reg); udelay(150); - if (INTEL_INFO(dev)->gen >= 4 && !HAS_PCH_SPLIT(dev)) { + if (INTEL_INFO(dev)->gen >= 4) { temp = 0; if (is_sdvo) { temp = intel_mode_get_pixel_multiplier(adjusted_mode); @@ -5116,30 +4895,16 @@ static int i9xx_crtc_mode_set(struct drm_crtc *crtc, /* pipesrc and dspsize control the size that is scaled from, * which should always be the user's requested size. */ - if (!HAS_PCH_SPLIT(dev)) { - I915_WRITE(DSPSIZE(plane), - ((mode->vdisplay - 1) << 16) | - (mode->hdisplay - 1)); - I915_WRITE(DSPPOS(plane), 0); - } + I915_WRITE(DSPSIZE(plane), + ((mode->vdisplay - 1) << 16) | + (mode->hdisplay - 1)); + I915_WRITE(DSPPOS(plane), 0); I915_WRITE(PIPESRC(pipe), ((mode->hdisplay - 1) << 16) | (mode->vdisplay - 1)); - if (HAS_PCH_SPLIT(dev)) { - I915_WRITE(PIPE_DATA_M1(pipe), TU_SIZE(m_n.tu) | m_n.gmch_m); - I915_WRITE(PIPE_DATA_N1(pipe), m_n.gmch_n); - I915_WRITE(PIPE_LINK_M1(pipe), m_n.link_m); - I915_WRITE(PIPE_LINK_N1(pipe), m_n.link_n); - - if (has_edp_encoder && !intel_encoder_is_pch_edp(&has_edp_encoder->base)) { - ironlake_set_pll_edp(crtc, adjusted_mode->clock); - } - } - I915_WRITE(PIPECONF(pipe), pipeconf); POSTING_READ(PIPECONF(pipe)); - if (!HAS_PCH_SPLIT(dev)) - intel_enable_pipe(dev_priv, pipe, false); + intel_enable_pipe(dev_priv, pipe, false); intel_wait_for_vblank(dev, pipe); -- cgit v1.1 From c713bb087e714f01082e6b8a85e98552e7bc6c3a Mon Sep 17 00:00:00 2001 From: Eric Anholt Date: Wed, 30 Mar 2011 13:01:05 -0700 Subject: drm/i915: Drop the eDP paths from the pre-Ironlake crtc_mode_set. While g4x had DP, eDP came with Ironlake, so we don't need that code here. Signed-off-by: Eric Anholt Reviewed-by: Jesse Barnes Signed-off-by: Chris Wilson --- drivers/gpu/drm/i915/intel_display.c | 57 +++++++++++++++--------------------- 1 file changed, 24 insertions(+), 33 deletions(-) (limited to 'drivers/gpu/drm/i915/intel_display.c') diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c index 622820b..08ff2f0 100644 --- a/drivers/gpu/drm/i915/intel_display.c +++ b/drivers/gpu/drm/i915/intel_display.c @@ -4533,7 +4533,6 @@ static int i9xx_crtc_mode_set(struct drm_crtc *crtc, u32 dpll, fp = 0, fp2 = 0, dspcntr, pipeconf; bool ok, has_reduced_clock = false, is_sdvo = false, is_dvo = false; bool is_crt = false, is_lvds = false, is_tv = false, is_dp = false; - struct intel_encoder *has_edp_encoder = NULL; struct drm_mode_config *mode_config = &dev->mode_config; struct intel_encoder *encoder; const intel_limit_t *limit; @@ -4567,9 +4566,6 @@ static int i9xx_crtc_mode_set(struct drm_crtc *crtc, case INTEL_OUTPUT_DISPLAYPORT: is_dp = true; break; - case INTEL_OUTPUT_EDP: - has_edp_encoder = encoder; - break; } num_connectors++; @@ -4750,14 +4746,11 @@ static int i9xx_crtc_mode_set(struct drm_crtc *crtc, fp_reg = FP0(pipe); dpll_reg = DPLL(pipe); - /* PCH eDP needs FDI, but CPU eDP does not */ - if (!has_edp_encoder) { - I915_WRITE(fp_reg, fp); - I915_WRITE(dpll_reg, dpll & ~DPLL_VCO_ENABLE); + I915_WRITE(fp_reg, fp); + I915_WRITE(dpll_reg, dpll & ~DPLL_VCO_ENABLE); - POSTING_READ(dpll_reg); - udelay(150); - } + POSTING_READ(dpll_reg); + udelay(150); /* The LVDS pin pair needs to be on before the DPLLs are enabled. * This is an exception to the general rule that mode_set doesn't turn @@ -4817,31 +4810,29 @@ static int i9xx_crtc_mode_set(struct drm_crtc *crtc, intel_dp_set_m_n(crtc, mode, adjusted_mode); } - if (!has_edp_encoder) { - I915_WRITE(dpll_reg, dpll); + I915_WRITE(dpll_reg, dpll); - /* Wait for the clocks to stabilize. */ - POSTING_READ(dpll_reg); - udelay(150); + /* Wait for the clocks to stabilize. */ + POSTING_READ(dpll_reg); + udelay(150); - if (INTEL_INFO(dev)->gen >= 4) { - temp = 0; - if (is_sdvo) { - temp = intel_mode_get_pixel_multiplier(adjusted_mode); - if (temp > 1) - temp = (temp - 1) << DPLL_MD_UDI_MULTIPLIER_SHIFT; - else - temp = 0; - } - I915_WRITE(DPLL_MD(pipe), temp); - } else { - /* The pixel multiplier can only be updated once the - * DPLL is enabled and the clocks are stable. - * - * So write it again. - */ - I915_WRITE(dpll_reg, dpll); + if (INTEL_INFO(dev)->gen >= 4) { + temp = 0; + if (is_sdvo) { + temp = intel_mode_get_pixel_multiplier(adjusted_mode); + if (temp > 1) + temp = (temp - 1) << DPLL_MD_UDI_MULTIPLIER_SHIFT; + else + temp = 0; } + I915_WRITE(DPLL_MD(pipe), temp); + } else { + /* The pixel multiplier can only be updated once the + * DPLL is enabled and the clocks are stable. + * + * So write it again. + */ + I915_WRITE(dpll_reg, dpll); } intel_crtc->lowfreq_avail = false; -- cgit v1.1 From db244b60e7f7f11825c6f36bcc8e8d8f3ca7cd36 Mon Sep 17 00:00:00 2001 From: Eric Anholt Date: Wed, 30 Mar 2011 13:01:06 -0700 Subject: drm/i915: Drop the remaining bit of Ironlake code from i9xx_crtc_mode_set(). Signed-off-by: Eric Anholt Reviewed-by: Jesse Barnes Signed-off-by: Chris Wilson --- drivers/gpu/drm/i915/intel_display.c | 6 ------ 1 file changed, 6 deletions(-) (limited to 'drivers/gpu/drm/i915/intel_display.c') diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c index 08ff2f0..a0d5a1a 100644 --- a/drivers/gpu/drm/i915/intel_display.c +++ b/drivers/gpu/drm/i915/intel_display.c @@ -4899,12 +4899,6 @@ static int i9xx_crtc_mode_set(struct drm_crtc *crtc, intel_wait_for_vblank(dev, pipe); - if (IS_GEN5(dev)) { - /* enable address swizzle for tiling buffer */ - temp = I915_READ(DISP_ARB_CTL); - I915_WRITE(DISP_ARB_CTL, temp | DISP_TILE_SURFACE_SWIZZLING); - } - I915_WRITE(DSPCNTR(plane), dspcntr); POSTING_READ(DSPCNTR(plane)); -- cgit v1.1 From 8febb2974faf0608111fd3c4dc36fa7f0f1cbfc2 Mon Sep 17 00:00:00 2001 From: Eric Anholt Date: Wed, 30 Mar 2011 13:01:07 -0700 Subject: drm/i915: Drop non-HAS_PCH_SPLIT() code from ironlake_crtc_mode_set(). Ironlake is where the PCH split started. Signed-off-by: Eric Anholt Signed-off-by: Chris Wilson --- drivers/gpu/drm/i915/intel_display.c | 359 +++++++++++++++-------------------- 1 file changed, 150 insertions(+), 209 deletions(-) (limited to 'drivers/gpu/drm/i915/intel_display.c') diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c index a0d5a1a..b41c87a 100644 --- a/drivers/gpu/drm/i915/intel_display.c +++ b/drivers/gpu/drm/i915/intel_display.c @@ -4934,7 +4934,7 @@ static int ironlake_crtc_mode_set(struct drm_crtc *crtc, struct fdi_m_n m_n = {0}; u32 reg, temp; u32 lvds_sync = 0; - int target_clock; + int target_clock, pixel_multiplier, lane, link_bw, bpp, factor; list_for_each_entry(encoder, &mode_config->encoder_list, base.head) { if (encoder->base.crtc != crtc) @@ -4976,8 +4976,8 @@ static int ironlake_crtc_mode_set(struct drm_crtc *crtc, refclk / 1000); } else if (!IS_GEN2(dev)) { refclk = 96000; - if (HAS_PCH_SPLIT(dev) && - (!has_edp_encoder || intel_encoder_is_pch_edp(&has_edp_encoder->base))) + if (!has_edp_encoder || + intel_encoder_is_pch_edp(&has_edp_encoder->base)) refclk = 120000; /* 120Mhz refclk */ } else { refclk = 48000; @@ -5036,140 +5036,137 @@ static int ironlake_crtc_mode_set(struct drm_crtc *crtc, } /* FDI link */ - if (HAS_PCH_SPLIT(dev)) { - int pixel_multiplier = intel_mode_get_pixel_multiplier(adjusted_mode); - int lane = 0, link_bw, bpp; - /* CPU eDP doesn't require FDI link, so just set DP M/N - according to current link config */ - if (has_edp_encoder && !intel_encoder_is_pch_edp(&has_edp_encoder->base)) { + pixel_multiplier = intel_mode_get_pixel_multiplier(adjusted_mode); + lane = 0; + /* CPU eDP doesn't require FDI link, so just set DP M/N + according to current link config */ + if (has_edp_encoder && + !intel_encoder_is_pch_edp(&has_edp_encoder->base)) { + target_clock = mode->clock; + intel_edp_link_config(has_edp_encoder, + &lane, &link_bw); + } else { + /* [e]DP over FDI requires target mode clock + instead of link clock */ + if (is_dp || intel_encoder_is_pch_edp(&has_edp_encoder->base)) target_clock = mode->clock; - intel_edp_link_config(has_edp_encoder, - &lane, &link_bw); - } else { - /* [e]DP over FDI requires target mode clock - instead of link clock */ - if (is_dp || intel_encoder_is_pch_edp(&has_edp_encoder->base)) - target_clock = mode->clock; - else - target_clock = adjusted_mode->clock; - - /* FDI is a binary signal running at ~2.7GHz, encoding - * each output octet as 10 bits. The actual frequency - * is stored as a divider into a 100MHz clock, and the - * mode pixel clock is stored in units of 1KHz. - * Hence the bw of each lane in terms of the mode signal - * is: - */ - link_bw = intel_fdi_link_freq(dev) * MHz(100)/KHz(1)/10; - } + else + target_clock = adjusted_mode->clock; + + /* FDI is a binary signal running at ~2.7GHz, encoding + * each output octet as 10 bits. The actual frequency + * is stored as a divider into a 100MHz clock, and the + * mode pixel clock is stored in units of 1KHz. + * Hence the bw of each lane in terms of the mode signal + * is: + */ + link_bw = intel_fdi_link_freq(dev) * MHz(100)/KHz(1)/10; + } - /* determine panel color depth */ - temp = I915_READ(PIPECONF(pipe)); - temp &= ~PIPE_BPC_MASK; - if (is_lvds) { - /* the BPC will be 6 if it is 18-bit LVDS panel */ - if ((I915_READ(PCH_LVDS) & LVDS_A3_POWER_MASK) == LVDS_A3_POWER_UP) - temp |= PIPE_8BPC; - else - temp |= PIPE_6BPC; - } else if (has_edp_encoder) { - switch (dev_priv->edp.bpp/3) { - case 8: - temp |= PIPE_8BPC; - break; - case 10: - temp |= PIPE_10BPC; - break; - case 6: - temp |= PIPE_6BPC; - break; - case 12: - temp |= PIPE_12BPC; - break; - } - } else + /* determine panel color depth */ + temp = I915_READ(PIPECONF(pipe)); + temp &= ~PIPE_BPC_MASK; + if (is_lvds) { + /* the BPC will be 6 if it is 18-bit LVDS panel */ + if ((I915_READ(PCH_LVDS) & LVDS_A3_POWER_MASK) == LVDS_A3_POWER_UP) + temp |= PIPE_8BPC; + else + temp |= PIPE_6BPC; + } else if (has_edp_encoder) { + switch (dev_priv->edp.bpp/3) { + case 8: temp |= PIPE_8BPC; - I915_WRITE(PIPECONF(pipe), temp); - - switch (temp & PIPE_BPC_MASK) { - case PIPE_8BPC: - bpp = 24; break; - case PIPE_10BPC: - bpp = 30; + case 10: + temp |= PIPE_10BPC; break; - case PIPE_6BPC: - bpp = 18; + case 6: + temp |= PIPE_6BPC; break; - case PIPE_12BPC: - bpp = 36; + case 12: + temp |= PIPE_12BPC; break; - default: - DRM_ERROR("unknown pipe bpc value\n"); - bpp = 24; - } - - if (!lane) { - /* - * Account for spread spectrum to avoid - * oversubscribing the link. Max center spread - * is 2.5%; use 5% for safety's sake. - */ - u32 bps = target_clock * bpp * 21 / 20; - lane = bps / (link_bw * 8) + 1; } + } else + temp |= PIPE_8BPC; + I915_WRITE(PIPECONF(pipe), temp); - intel_crtc->fdi_lanes = lane; + switch (temp & PIPE_BPC_MASK) { + case PIPE_8BPC: + bpp = 24; + break; + case PIPE_10BPC: + bpp = 30; + break; + case PIPE_6BPC: + bpp = 18; + break; + case PIPE_12BPC: + bpp = 36; + break; + default: + DRM_ERROR("unknown pipe bpc value\n"); + bpp = 24; + } - if (pixel_multiplier > 1) - link_bw *= pixel_multiplier; - ironlake_compute_m_n(bpp, lane, target_clock, link_bw, &m_n); + if (!lane) { + /* + * Account for spread spectrum to avoid + * oversubscribing the link. Max center spread + * is 2.5%; use 5% for safety's sake. + */ + u32 bps = target_clock * bpp * 21 / 20; + lane = bps / (link_bw * 8) + 1; } + intel_crtc->fdi_lanes = lane; + + if (pixel_multiplier > 1) + link_bw *= pixel_multiplier; + ironlake_compute_m_n(bpp, lane, target_clock, link_bw, &m_n); + /* Ironlake: try to setup display ref clock before DPLL * enabling. This is only under driver's control after * PCH B stepping, previous chipset stepping should be * ignoring this setting. */ - if (HAS_PCH_SPLIT(dev)) { - temp = I915_READ(PCH_DREF_CONTROL); - /* Always enable nonspread source */ - temp &= ~DREF_NONSPREAD_SOURCE_MASK; - temp |= DREF_NONSPREAD_SOURCE_ENABLE; - temp &= ~DREF_SSC_SOURCE_MASK; - temp |= DREF_SSC_SOURCE_ENABLE; - I915_WRITE(PCH_DREF_CONTROL, temp); - - POSTING_READ(PCH_DREF_CONTROL); - udelay(200); - - if (has_edp_encoder) { - if (intel_panel_use_ssc(dev_priv)) { - temp |= DREF_SSC1_ENABLE; - I915_WRITE(PCH_DREF_CONTROL, temp); - - POSTING_READ(PCH_DREF_CONTROL); - udelay(200); - } - temp &= ~DREF_CPU_SOURCE_OUTPUT_MASK; + temp = I915_READ(PCH_DREF_CONTROL); + /* Always enable nonspread source */ + temp &= ~DREF_NONSPREAD_SOURCE_MASK; + temp |= DREF_NONSPREAD_SOURCE_ENABLE; + temp &= ~DREF_SSC_SOURCE_MASK; + temp |= DREF_SSC_SOURCE_ENABLE; + I915_WRITE(PCH_DREF_CONTROL, temp); + + POSTING_READ(PCH_DREF_CONTROL); + udelay(200); - /* Enable CPU source on CPU attached eDP */ - if (!intel_encoder_is_pch_edp(&has_edp_encoder->base)) { - if (intel_panel_use_ssc(dev_priv)) - temp |= DREF_CPU_SOURCE_OUTPUT_DOWNSPREAD; - else - temp |= DREF_CPU_SOURCE_OUTPUT_NONSPREAD; - } else { - /* Enable SSC on PCH eDP if needed */ - if (intel_panel_use_ssc(dev_priv)) { - DRM_ERROR("enabling SSC on PCH\n"); - temp |= DREF_SUPERSPREAD_SOURCE_ENABLE; - } - } + if (has_edp_encoder) { + if (intel_panel_use_ssc(dev_priv)) { + temp |= DREF_SSC1_ENABLE; I915_WRITE(PCH_DREF_CONTROL, temp); + POSTING_READ(PCH_DREF_CONTROL); udelay(200); } + temp &= ~DREF_CPU_SOURCE_OUTPUT_MASK; + + /* Enable CPU source on CPU attached eDP */ + if (!intel_encoder_is_pch_edp(&has_edp_encoder->base)) { + if (intel_panel_use_ssc(dev_priv)) + temp |= DREF_CPU_SOURCE_OUTPUT_DOWNSPREAD; + else + temp |= DREF_CPU_SOURCE_OUTPUT_NONSPREAD; + } else { + /* Enable SSC on PCH eDP if needed */ + if (intel_panel_use_ssc(dev_priv)) { + DRM_ERROR("enabling SSC on PCH\n"); + temp |= DREF_SUPERSPREAD_SOURCE_ENABLE; + } + } + I915_WRITE(PCH_DREF_CONTROL, temp); + POSTING_READ(PCH_DREF_CONTROL); + udelay(200); } if (IS_PINEVIEW(dev)) { @@ -5185,24 +5182,19 @@ static int ironlake_crtc_mode_set(struct drm_crtc *crtc, } /* Enable autotuning of the PLL clock (if permissible) */ - if (HAS_PCH_SPLIT(dev)) { - int factor = 21; - - if (is_lvds) { - if ((intel_panel_use_ssc(dev_priv) && - dev_priv->lvds_ssc_freq == 100) || - (I915_READ(PCH_LVDS) & LVDS_CLKB_POWER_MASK) == LVDS_CLKB_POWER_UP) - factor = 25; - } else if (is_sdvo && is_tv) - factor = 20; + factor = 21; + if (is_lvds) { + if ((intel_panel_use_ssc(dev_priv) && + dev_priv->lvds_ssc_freq == 100) || + (I915_READ(PCH_LVDS) & LVDS_CLKB_POWER_MASK) == LVDS_CLKB_POWER_UP) + factor = 25; + } else if (is_sdvo && is_tv) + factor = 20; - if (clock.m1 < factor * clock.n) - fp |= FP_CB_TUNE; - } + if (clock.m1 < factor * clock.n) + fp |= FP_CB_TUNE; dpll = 0; - if (!HAS_PCH_SPLIT(dev)) - dpll = DPLL_VGA_MODE_DIS; if (!IS_GEN2(dev)) { if (is_lvds) @@ -5214,7 +5206,7 @@ static int ironlake_crtc_mode_set(struct drm_crtc *crtc, if (pixel_multiplier > 1) { if (IS_I945G(dev) || IS_I945GM(dev) || IS_G33(dev)) dpll |= (pixel_multiplier - 1) << SDVO_MULTIPLIER_SHIFT_HIRES; - else if (HAS_PCH_SPLIT(dev)) + else dpll |= (pixel_multiplier - 1) << PLL_REF_SDVO_HDMI_MULTIPLIER_SHIFT; } dpll |= DPLL_DVO_HIGH_SPEED; @@ -5228,8 +5220,7 @@ static int ironlake_crtc_mode_set(struct drm_crtc *crtc, else { dpll |= (1 << (clock.p1 - 1)) << DPLL_FPA01_P1_POST_DIV_SHIFT; /* also FPA1 */ - if (HAS_PCH_SPLIT(dev)) - dpll |= (1 << (clock.p1 - 1)) << DPLL_FPA1_P1_POST_DIV_SHIFT; + dpll |= (1 << (clock.p1 - 1)) << DPLL_FPA1_P1_POST_DIV_SHIFT; if (IS_G4X(dev) && has_reduced_clock) dpll |= (1 << (reduced_clock.p1 - 1)) << DPLL_FPA1_P1_POST_DIV_SHIFT; } @@ -5247,8 +5238,6 @@ static int ironlake_crtc_mode_set(struct drm_crtc *crtc, dpll |= DPLLB_LVDS_P2_CLOCK_DIV_14; break; } - if (INTEL_INFO(dev)->gen >= 4 && !HAS_PCH_SPLIT(dev)) - dpll |= (6 << PLL_LOAD_PULSE_PHASE_SHIFT); } else { if (is_lvds) { dpll |= (1 << (clock.p1 - 1)) << DPLL_FPA01_P1_POST_DIV_SHIFT; @@ -5279,15 +5268,6 @@ static int ironlake_crtc_mode_set(struct drm_crtc *crtc, /* Set up the display plane register */ dspcntr = DISPPLANE_GAMMA_ENABLE; - /* Ironlake's plane is forced to pipe, bit 24 is to - enable color space conversion */ - if (!HAS_PCH_SPLIT(dev)) { - if (pipe == 0) - dspcntr &= ~DISPPLANE_SEL_PIPE_MASK; - else - dspcntr |= DISPPLANE_SEL_PIPE_B; - } - if (pipe == 0 && INTEL_INFO(dev)->gen < 4) { /* Enable pixel doubling when the dot clock is > 90% of the (display) * core speed. @@ -5302,20 +5282,12 @@ static int ironlake_crtc_mode_set(struct drm_crtc *crtc, pipeconf &= ~PIPECONF_DOUBLE_WIDE; } - if (!HAS_PCH_SPLIT(dev)) - dpll |= DPLL_VCO_ENABLE; - DRM_DEBUG_KMS("Mode for pipe %c:\n", pipe == 0 ? 'A' : 'B'); drm_mode_debug_printmodeline(mode); /* assign to Ironlake registers */ - if (HAS_PCH_SPLIT(dev)) { - fp_reg = PCH_FP0(pipe); - dpll_reg = PCH_DPLL(pipe); - } else { - fp_reg = FP0(pipe); - dpll_reg = DPLL(pipe); - } + fp_reg = PCH_FP0(pipe); + dpll_reg = PCH_DPLL(pipe); /* PCH eDP needs FDI, but CPU eDP does not */ if (!has_edp_encoder || intel_encoder_is_pch_edp(&has_edp_encoder->base)) { @@ -5354,9 +5326,7 @@ static int ironlake_crtc_mode_set(struct drm_crtc *crtc, * things on. */ if (is_lvds) { - reg = LVDS; - if (HAS_PCH_SPLIT(dev)) - reg = PCH_LVDS; + reg = PCH_LVDS; temp = I915_READ(reg); temp |= LVDS_PORT_EN | LVDS_A0A2_CLKA_POWER_UP; @@ -5385,13 +5355,6 @@ static int ironlake_crtc_mode_set(struct drm_crtc *crtc, * appropriately here, but we need to look more thoroughly into how * panels behave in the two modes. */ - /* set the dithering flag on non-PCH LVDS as needed */ - if (INTEL_INFO(dev)->gen >= 4 && !HAS_PCH_SPLIT(dev)) { - if (dev_priv->lvds_dither) - temp |= LVDS_ENABLE_DITHER; - else - temp &= ~LVDS_ENABLE_DITHER; - } if (adjusted_mode->flags & DRM_MODE_FLAG_NHSYNC) lvds_sync |= LVDS_HSYNC_POLARITY; if (adjusted_mode->flags & DRM_MODE_FLAG_NVSYNC) @@ -5412,18 +5375,16 @@ static int ironlake_crtc_mode_set(struct drm_crtc *crtc, } /* set the dithering flag and clear for anything other than a panel. */ - if (HAS_PCH_SPLIT(dev)) { - pipeconf &= ~PIPECONF_DITHER_EN; - pipeconf &= ~PIPECONF_DITHER_TYPE_MASK; - if (dev_priv->lvds_dither && (is_lvds || has_edp_encoder)) { - pipeconf |= PIPECONF_DITHER_EN; - pipeconf |= PIPECONF_DITHER_TYPE_ST1; - } + pipeconf &= ~PIPECONF_DITHER_EN; + pipeconf &= ~PIPECONF_DITHER_TYPE_MASK; + if (dev_priv->lvds_dither && (is_lvds || has_edp_encoder)) { + pipeconf |= PIPECONF_DITHER_EN; + pipeconf |= PIPECONF_DITHER_TYPE_ST1; } if (is_dp || intel_encoder_is_pch_edp(&has_edp_encoder->base)) { intel_dp_set_m_n(crtc, mode, adjusted_mode); - } else if (HAS_PCH_SPLIT(dev)) { + } else { /* For non-DP output, clear any trans DP clock recovery setting.*/ I915_WRITE(TRANSDATA_M1(pipe), 0); I915_WRITE(TRANSDATA_N1(pipe), 0); @@ -5431,31 +5392,20 @@ static int ironlake_crtc_mode_set(struct drm_crtc *crtc, I915_WRITE(TRANSDPLINK_N1(pipe), 0); } - if (!has_edp_encoder || intel_encoder_is_pch_edp(&has_edp_encoder->base)) { + if (!has_edp_encoder || + intel_encoder_is_pch_edp(&has_edp_encoder->base)) { I915_WRITE(dpll_reg, dpll); /* Wait for the clocks to stabilize. */ POSTING_READ(dpll_reg); udelay(150); - if (INTEL_INFO(dev)->gen >= 4 && !HAS_PCH_SPLIT(dev)) { - temp = 0; - if (is_sdvo) { - temp = intel_mode_get_pixel_multiplier(adjusted_mode); - if (temp > 1) - temp = (temp - 1) << DPLL_MD_UDI_MULTIPLIER_SHIFT; - else - temp = 0; - } - I915_WRITE(DPLL_MD(pipe), temp); - } else { - /* The pixel multiplier can only be updated once the - * DPLL is enabled and the clocks are stable. - * - * So write it again. - */ - I915_WRITE(dpll_reg, dpll); - } + /* The pixel multiplier can only be updated once the + * DPLL is enabled and the clocks are stable. + * + * So write it again. + */ + I915_WRITE(dpll_reg, dpll); } intel_crtc->lowfreq_avail = false; @@ -5506,33 +5456,24 @@ static int ironlake_crtc_mode_set(struct drm_crtc *crtc, (adjusted_mode->crtc_vsync_start - 1) | ((adjusted_mode->crtc_vsync_end - 1) << 16)); - /* pipesrc and dspsize control the size that is scaled from, - * which should always be the user's requested size. + /* pipesrc controls the size that is scaled from, which should + * always be the user's requested size. */ - if (!HAS_PCH_SPLIT(dev)) { - I915_WRITE(DSPSIZE(plane), - ((mode->vdisplay - 1) << 16) | - (mode->hdisplay - 1)); - I915_WRITE(DSPPOS(plane), 0); - } I915_WRITE(PIPESRC(pipe), ((mode->hdisplay - 1) << 16) | (mode->vdisplay - 1)); - if (HAS_PCH_SPLIT(dev)) { - I915_WRITE(PIPE_DATA_M1(pipe), TU_SIZE(m_n.tu) | m_n.gmch_m); - I915_WRITE(PIPE_DATA_N1(pipe), m_n.gmch_n); - I915_WRITE(PIPE_LINK_M1(pipe), m_n.link_m); - I915_WRITE(PIPE_LINK_N1(pipe), m_n.link_n); + I915_WRITE(PIPE_DATA_M1(pipe), TU_SIZE(m_n.tu) | m_n.gmch_m); + I915_WRITE(PIPE_DATA_N1(pipe), m_n.gmch_n); + I915_WRITE(PIPE_LINK_M1(pipe), m_n.link_m); + I915_WRITE(PIPE_LINK_N1(pipe), m_n.link_n); - if (has_edp_encoder && !intel_encoder_is_pch_edp(&has_edp_encoder->base)) { - ironlake_set_pll_edp(crtc, adjusted_mode->clock); - } + if (has_edp_encoder && + !intel_encoder_is_pch_edp(&has_edp_encoder->base)) { + ironlake_set_pll_edp(crtc, adjusted_mode->clock); } I915_WRITE(PIPECONF(pipe), pipeconf); POSTING_READ(PIPECONF(pipe)); - if (!HAS_PCH_SPLIT(dev)) - intel_enable_pipe(dev_priv, pipe, false); intel_wait_for_vblank(dev, pipe); -- cgit v1.1 From a07d67870565e1015935f7a8d8d6ac5f507442c5 Mon Sep 17 00:00:00 2001 From: Eric Anholt Date: Wed, 30 Mar 2011 13:01:08 -0700 Subject: drm/i915: Drop remaining pre-Ironlake code from ironlake_crtc_mode_set(). Signed-off-by: Eric Anholt Signed-off-by: Chris Wilson --- drivers/gpu/drm/i915/intel_display.c | 119 +++++++++++------------------------ 1 file changed, 36 insertions(+), 83 deletions(-) (limited to 'drivers/gpu/drm/i915/intel_display.c') diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c index b41c87a..832210b 100644 --- a/drivers/gpu/drm/i915/intel_display.c +++ b/drivers/gpu/drm/i915/intel_display.c @@ -4924,7 +4924,7 @@ static int ironlake_crtc_mode_set(struct drm_crtc *crtc, int refclk, num_connectors = 0; intel_clock_t clock, reduced_clock; u32 dpll, fp = 0, fp2 = 0, dspcntr, pipeconf; - bool ok, has_reduced_clock = false, is_sdvo = false, is_dvo = false; + bool ok, has_reduced_clock = false, is_sdvo = false; bool is_crt = false, is_lvds = false, is_tv = false, is_dp = false; struct intel_encoder *has_edp_encoder = NULL; struct drm_mode_config *mode_config = &dev->mode_config; @@ -4950,9 +4950,6 @@ static int ironlake_crtc_mode_set(struct drm_crtc *crtc, if (encoder->needs_tv_clock) is_tv = true; break; - case INTEL_OUTPUT_DVO: - is_dvo = true; - break; case INTEL_OUTPUT_TVOUT: is_tv = true; break; @@ -4974,13 +4971,11 @@ static int ironlake_crtc_mode_set(struct drm_crtc *crtc, refclk = dev_priv->lvds_ssc_freq * 1000; DRM_DEBUG_KMS("using SSC reference clock of %d MHz\n", refclk / 1000); - } else if (!IS_GEN2(dev)) { + } else { refclk = 96000; if (!has_edp_encoder || intel_encoder_is_pch_edp(&has_edp_encoder->base)) refclk = 120000; /* 120Mhz refclk */ - } else { - refclk = 48000; } /* @@ -5169,17 +5164,10 @@ static int ironlake_crtc_mode_set(struct drm_crtc *crtc, udelay(200); } - if (IS_PINEVIEW(dev)) { - fp = (1 << clock.n) << 16 | clock.m1 << 8 | clock.m2; - if (has_reduced_clock) - fp2 = (1 << reduced_clock.n) << 16 | - reduced_clock.m1 << 8 | reduced_clock.m2; - } else { - fp = clock.n << 16 | clock.m1 << 8 | clock.m2; - if (has_reduced_clock) - fp2 = reduced_clock.n << 16 | reduced_clock.m1 << 8 | - reduced_clock.m2; - } + fp = clock.n << 16 | clock.m1 << 8 | clock.m2; + if (has_reduced_clock) + fp2 = reduced_clock.n << 16 | reduced_clock.m1 << 8 | + reduced_clock.m2; /* Enable autotuning of the PLL clock (if permissible) */ factor = 21; @@ -5196,59 +5184,38 @@ static int ironlake_crtc_mode_set(struct drm_crtc *crtc, dpll = 0; - if (!IS_GEN2(dev)) { - if (is_lvds) - dpll |= DPLLB_MODE_LVDS; - else - dpll |= DPLLB_MODE_DAC_SERIAL; - if (is_sdvo) { - int pixel_multiplier = intel_mode_get_pixel_multiplier(adjusted_mode); - if (pixel_multiplier > 1) { - if (IS_I945G(dev) || IS_I945GM(dev) || IS_G33(dev)) - dpll |= (pixel_multiplier - 1) << SDVO_MULTIPLIER_SHIFT_HIRES; - else - dpll |= (pixel_multiplier - 1) << PLL_REF_SDVO_HDMI_MULTIPLIER_SHIFT; - } - dpll |= DPLL_DVO_HIGH_SPEED; + if (is_lvds) + dpll |= DPLLB_MODE_LVDS; + else + dpll |= DPLLB_MODE_DAC_SERIAL; + if (is_sdvo) { + int pixel_multiplier = intel_mode_get_pixel_multiplier(adjusted_mode); + if (pixel_multiplier > 1) { + dpll |= (pixel_multiplier - 1) << PLL_REF_SDVO_HDMI_MULTIPLIER_SHIFT; } - if (is_dp || intel_encoder_is_pch_edp(&has_edp_encoder->base)) - dpll |= DPLL_DVO_HIGH_SPEED; + dpll |= DPLL_DVO_HIGH_SPEED; + } + if (is_dp || intel_encoder_is_pch_edp(&has_edp_encoder->base)) + dpll |= DPLL_DVO_HIGH_SPEED; - /* compute bitmask from p1 value */ - if (IS_PINEVIEW(dev)) - dpll |= (1 << (clock.p1 - 1)) << DPLL_FPA01_P1_POST_DIV_SHIFT_PINEVIEW; - else { - dpll |= (1 << (clock.p1 - 1)) << DPLL_FPA01_P1_POST_DIV_SHIFT; - /* also FPA1 */ - dpll |= (1 << (clock.p1 - 1)) << DPLL_FPA1_P1_POST_DIV_SHIFT; - if (IS_G4X(dev) && has_reduced_clock) - dpll |= (1 << (reduced_clock.p1 - 1)) << DPLL_FPA1_P1_POST_DIV_SHIFT; - } - switch (clock.p2) { - case 5: - dpll |= DPLL_DAC_SERIAL_P2_CLOCK_DIV_5; - break; - case 7: - dpll |= DPLLB_LVDS_P2_CLOCK_DIV_7; - break; - case 10: - dpll |= DPLL_DAC_SERIAL_P2_CLOCK_DIV_10; - break; - case 14: - dpll |= DPLLB_LVDS_P2_CLOCK_DIV_14; - break; - } - } else { - if (is_lvds) { - dpll |= (1 << (clock.p1 - 1)) << DPLL_FPA01_P1_POST_DIV_SHIFT; - } else { - if (clock.p1 == 2) - dpll |= PLL_P1_DIVIDE_BY_TWO; - else - dpll |= (clock.p1 - 2) << DPLL_FPA01_P1_POST_DIV_SHIFT; - if (clock.p2 == 4) - dpll |= PLL_P2_DIVIDE_BY_4; - } + /* compute bitmask from p1 value */ + dpll |= (1 << (clock.p1 - 1)) << DPLL_FPA01_P1_POST_DIV_SHIFT; + /* also FPA1 */ + dpll |= (1 << (clock.p1 - 1)) << DPLL_FPA1_P1_POST_DIV_SHIFT; + + switch (clock.p2) { + case 5: + dpll |= DPLL_DAC_SERIAL_P2_CLOCK_DIV_5; + break; + case 7: + dpll |= DPLLB_LVDS_P2_CLOCK_DIV_7; + break; + case 10: + dpll |= DPLL_DAC_SERIAL_P2_CLOCK_DIV_10; + break; + case 14: + dpll |= DPLLB_LVDS_P2_CLOCK_DIV_14; + break; } if (is_sdvo && is_tv) @@ -5268,20 +5235,6 @@ static int ironlake_crtc_mode_set(struct drm_crtc *crtc, /* Set up the display plane register */ dspcntr = DISPPLANE_GAMMA_ENABLE; - if (pipe == 0 && INTEL_INFO(dev)->gen < 4) { - /* Enable pixel doubling when the dot clock is > 90% of the (display) - * core speed. - * - * XXX: No double-wide on 915GM pipe B. Is that the only reason for the - * pipe == 0 check? - */ - if (mode->clock > - dev_priv->display.get_display_clock_speed(dev) * 9 / 10) - pipeconf |= PIPECONF_DOUBLE_WIDE; - else - pipeconf &= ~PIPECONF_DOUBLE_WIDE; - } - DRM_DEBUG_KMS("Mode for pipe %c:\n", pipe == 0 ? 'A' : 'B'); drm_mode_debug_printmodeline(mode); -- cgit v1.1 From fae14981ce89fede363a8d4ddda7f7ca587195ff Mon Sep 17 00:00:00 2001 From: Eric Anholt Date: Wed, 30 Mar 2011 13:01:09 -0700 Subject: drm/i915: Clean up leftover DPLL and LVDS register choice from pch split. We used to have these from the product of (pch, non-pch) * (pipe a, pipe b). Now we can just use the nice per-pipe reg macros in the split out crtc_mode_sets. Signed-off-by: Eric Anholt Signed-off-by: Chris Wilson --- drivers/gpu/drm/i915/intel_display.c | 57 ++++++++++++++---------------------- 1 file changed, 22 insertions(+), 35 deletions(-) (limited to 'drivers/gpu/drm/i915/intel_display.c') diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c index 832210b..39bf389 100644 --- a/drivers/gpu/drm/i915/intel_display.c +++ b/drivers/gpu/drm/i915/intel_display.c @@ -4527,7 +4527,6 @@ static int i9xx_crtc_mode_set(struct drm_crtc *crtc, struct intel_crtc *intel_crtc = to_intel_crtc(crtc); int pipe = intel_crtc->pipe; int plane = intel_crtc->plane; - u32 fp_reg, dpll_reg; int refclk, num_connectors = 0; intel_clock_t clock, reduced_clock; u32 dpll, fp = 0, fp2 = 0, dspcntr, pipeconf; @@ -4537,7 +4536,7 @@ static int i9xx_crtc_mode_set(struct drm_crtc *crtc, struct intel_encoder *encoder; const intel_limit_t *limit; int ret; - u32 reg, temp; + u32 temp; u32 lvds_sync = 0; list_for_each_entry(encoder, &mode_config->encoder_list, base.head) { @@ -4743,13 +4742,10 @@ static int i9xx_crtc_mode_set(struct drm_crtc *crtc, DRM_DEBUG_KMS("Mode for pipe %c:\n", pipe == 0 ? 'A' : 'B'); drm_mode_debug_printmodeline(mode); - fp_reg = FP0(pipe); - dpll_reg = DPLL(pipe); + I915_WRITE(FP0(pipe), fp); + I915_WRITE(DPLL(pipe), dpll & ~DPLL_VCO_ENABLE); - I915_WRITE(fp_reg, fp); - I915_WRITE(dpll_reg, dpll & ~DPLL_VCO_ENABLE); - - POSTING_READ(dpll_reg); + POSTING_READ(DPLL(pipe)); udelay(150); /* The LVDS pin pair needs to be on before the DPLLs are enabled. @@ -4757,9 +4753,7 @@ static int i9xx_crtc_mode_set(struct drm_crtc *crtc, * things on. */ if (is_lvds) { - reg = LVDS; - - temp = I915_READ(reg); + temp = I915_READ(LVDS); temp |= LVDS_PORT_EN | LVDS_A0A2_CLKA_POWER_UP; if (pipe == 1) { temp |= LVDS_PIPEB_SELECT; @@ -4803,17 +4797,17 @@ static int i9xx_crtc_mode_set(struct drm_crtc *crtc, temp &= ~(LVDS_HSYNC_POLARITY | LVDS_VSYNC_POLARITY); temp |= lvds_sync; } - I915_WRITE(reg, temp); + I915_WRITE(LVDS, temp); } if (is_dp) { intel_dp_set_m_n(crtc, mode, adjusted_mode); } - I915_WRITE(dpll_reg, dpll); + I915_WRITE(DPLL(pipe), dpll); /* Wait for the clocks to stabilize. */ - POSTING_READ(dpll_reg); + POSTING_READ(DPLL(pipe)); udelay(150); if (INTEL_INFO(dev)->gen >= 4) { @@ -4832,19 +4826,19 @@ static int i9xx_crtc_mode_set(struct drm_crtc *crtc, * * So write it again. */ - I915_WRITE(dpll_reg, dpll); + I915_WRITE(DPLL(pipe), dpll); } intel_crtc->lowfreq_avail = false; if (is_lvds && has_reduced_clock && i915_powersave) { - I915_WRITE(fp_reg + 4, fp2); + I915_WRITE(FP1(pipe), fp2); intel_crtc->lowfreq_avail = true; if (HAS_PIPE_CXSR(dev)) { DRM_DEBUG_KMS("enabling CxSR downclocking\n"); pipeconf |= PIPECONF_CXSR_DOWNCLOCK; } } else { - I915_WRITE(fp_reg + 4, fp); + I915_WRITE(FP1(pipe), fp); if (HAS_PIPE_CXSR(dev)) { DRM_DEBUG_KMS("disabling CxSR downclocking\n"); pipeconf &= ~PIPECONF_CXSR_DOWNCLOCK; @@ -4920,7 +4914,6 @@ static int ironlake_crtc_mode_set(struct drm_crtc *crtc, struct intel_crtc *intel_crtc = to_intel_crtc(crtc); int pipe = intel_crtc->pipe; int plane = intel_crtc->plane; - u32 fp_reg, dpll_reg; int refclk, num_connectors = 0; intel_clock_t clock, reduced_clock; u32 dpll, fp = 0, fp2 = 0, dspcntr, pipeconf; @@ -4932,7 +4925,7 @@ static int ironlake_crtc_mode_set(struct drm_crtc *crtc, const intel_limit_t *limit; int ret; struct fdi_m_n m_n = {0}; - u32 reg, temp; + u32 temp; u32 lvds_sync = 0; int target_clock, pixel_multiplier, lane, link_bw, bpp, factor; @@ -5238,16 +5231,12 @@ static int ironlake_crtc_mode_set(struct drm_crtc *crtc, DRM_DEBUG_KMS("Mode for pipe %c:\n", pipe == 0 ? 'A' : 'B'); drm_mode_debug_printmodeline(mode); - /* assign to Ironlake registers */ - fp_reg = PCH_FP0(pipe); - dpll_reg = PCH_DPLL(pipe); - /* PCH eDP needs FDI, but CPU eDP does not */ if (!has_edp_encoder || intel_encoder_is_pch_edp(&has_edp_encoder->base)) { - I915_WRITE(fp_reg, fp); - I915_WRITE(dpll_reg, dpll & ~DPLL_VCO_ENABLE); + I915_WRITE(PCH_FP0(pipe), fp); + I915_WRITE(PCH_DPLL(pipe), dpll & ~DPLL_VCO_ENABLE); - POSTING_READ(dpll_reg); + POSTING_READ(PCH_DPLL(pipe)); udelay(150); } @@ -5279,9 +5268,7 @@ static int ironlake_crtc_mode_set(struct drm_crtc *crtc, * things on. */ if (is_lvds) { - reg = PCH_LVDS; - - temp = I915_READ(reg); + temp = I915_READ(PCH_LVDS); temp |= LVDS_PORT_EN | LVDS_A0A2_CLKA_POWER_UP; if (pipe == 1) { if (HAS_PCH_CPT(dev)) @@ -5324,7 +5311,7 @@ static int ironlake_crtc_mode_set(struct drm_crtc *crtc, temp &= ~(LVDS_HSYNC_POLARITY | LVDS_VSYNC_POLARITY); temp |= lvds_sync; } - I915_WRITE(reg, temp); + I915_WRITE(PCH_LVDS, temp); } /* set the dithering flag and clear for anything other than a panel. */ @@ -5347,10 +5334,10 @@ static int ironlake_crtc_mode_set(struct drm_crtc *crtc, if (!has_edp_encoder || intel_encoder_is_pch_edp(&has_edp_encoder->base)) { - I915_WRITE(dpll_reg, dpll); + I915_WRITE(PCH_DPLL(pipe), dpll); /* Wait for the clocks to stabilize. */ - POSTING_READ(dpll_reg); + POSTING_READ(PCH_DPLL(pipe)); udelay(150); /* The pixel multiplier can only be updated once the @@ -5358,19 +5345,19 @@ static int ironlake_crtc_mode_set(struct drm_crtc *crtc, * * So write it again. */ - I915_WRITE(dpll_reg, dpll); + I915_WRITE(PCH_DPLL(pipe), dpll); } intel_crtc->lowfreq_avail = false; if (is_lvds && has_reduced_clock && i915_powersave) { - I915_WRITE(fp_reg + 4, fp2); + I915_WRITE(PCH_FP1(pipe), fp2); intel_crtc->lowfreq_avail = true; if (HAS_PIPE_CXSR(dev)) { DRM_DEBUG_KMS("enabling CxSR downclocking\n"); pipeconf |= PIPECONF_CXSR_DOWNCLOCK; } } else { - I915_WRITE(fp_reg + 4, fp); + I915_WRITE(PCH_FP1(pipe), fp); if (HAS_PIPE_CXSR(dev)) { DRM_DEBUG_KMS("disabling CxSR downclocking\n"); pipeconf &= ~PIPECONF_CXSR_DOWNCLOCK; -- cgit v1.1 From 273e27ca8081095a1bdf65276d4b645215ad1c57 Mon Sep 17 00:00:00 2001 From: Eric Anholt Date: Wed, 30 Mar 2011 13:01:10 -0700 Subject: drm/i915: Fold the DPLL limit defines into the structs that use them. They're used in one place, and not providing any descriptive value, with their names just being approximately the conjunction of the struct name and the struct field. This diff was produced with gcc -E, copying the new struct definitions out, moving a couple of the old comments into place in the new structs, and reindenting. Signed-off-by: Eric Anholt Signed-off-by: Chris Wilson --- drivers/gpu/drm/i915/intel_display.c | 650 ++++++++++------------------------- 1 file changed, 181 insertions(+), 469 deletions(-) (limited to 'drivers/gpu/drm/i915/intel_display.c') diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c index 39bf389..bcef1c1 100644 --- a/drivers/gpu/drm/i915/intel_display.c +++ b/drivers/gpu/drm/i915/intel_display.c @@ -76,255 +76,6 @@ struct intel_limit { int, int, intel_clock_t *); }; -#define I8XX_DOT_MIN 25000 -#define I8XX_DOT_MAX 350000 -#define I8XX_VCO_MIN 930000 -#define I8XX_VCO_MAX 1400000 -#define I8XX_N_MIN 3 -#define I8XX_N_MAX 16 -#define I8XX_M_MIN 96 -#define I8XX_M_MAX 140 -#define I8XX_M1_MIN 18 -#define I8XX_M1_MAX 26 -#define I8XX_M2_MIN 6 -#define I8XX_M2_MAX 16 -#define I8XX_P_MIN 4 -#define I8XX_P_MAX 128 -#define I8XX_P1_MIN 2 -#define I8XX_P1_MAX 33 -#define I8XX_P1_LVDS_MIN 1 -#define I8XX_P1_LVDS_MAX 6 -#define I8XX_P2_SLOW 4 -#define I8XX_P2_FAST 2 -#define I8XX_P2_LVDS_SLOW 14 -#define I8XX_P2_LVDS_FAST 7 -#define I8XX_P2_SLOW_LIMIT 165000 - -#define I9XX_DOT_MIN 20000 -#define I9XX_DOT_MAX 400000 -#define I9XX_VCO_MIN 1400000 -#define I9XX_VCO_MAX 2800000 -#define PINEVIEW_VCO_MIN 1700000 -#define PINEVIEW_VCO_MAX 3500000 -#define I9XX_N_MIN 1 -#define I9XX_N_MAX 6 -/* Pineview's Ncounter is a ring counter */ -#define PINEVIEW_N_MIN 3 -#define PINEVIEW_N_MAX 6 -#define I9XX_M_MIN 70 -#define I9XX_M_MAX 120 -#define PINEVIEW_M_MIN 2 -#define PINEVIEW_M_MAX 256 -#define I9XX_M1_MIN 10 -#define I9XX_M1_MAX 22 -#define I9XX_M2_MIN 5 -#define I9XX_M2_MAX 9 -/* Pineview M1 is reserved, and must be 0 */ -#define PINEVIEW_M1_MIN 0 -#define PINEVIEW_M1_MAX 0 -#define PINEVIEW_M2_MIN 0 -#define PINEVIEW_M2_MAX 254 -#define I9XX_P_SDVO_DAC_MIN 5 -#define I9XX_P_SDVO_DAC_MAX 80 -#define I9XX_P_LVDS_MIN 7 -#define I9XX_P_LVDS_MAX 98 -#define PINEVIEW_P_LVDS_MIN 7 -#define PINEVIEW_P_LVDS_MAX 112 -#define I9XX_P1_MIN 1 -#define I9XX_P1_MAX 8 -#define I9XX_P2_SDVO_DAC_SLOW 10 -#define I9XX_P2_SDVO_DAC_FAST 5 -#define I9XX_P2_SDVO_DAC_SLOW_LIMIT 200000 -#define I9XX_P2_LVDS_SLOW 14 -#define I9XX_P2_LVDS_FAST 7 -#define I9XX_P2_LVDS_SLOW_LIMIT 112000 - -/*The parameter is for SDVO on G4x platform*/ -#define G4X_DOT_SDVO_MIN 25000 -#define G4X_DOT_SDVO_MAX 270000 -#define G4X_VCO_MIN 1750000 -#define G4X_VCO_MAX 3500000 -#define G4X_N_SDVO_MIN 1 -#define G4X_N_SDVO_MAX 4 -#define G4X_M_SDVO_MIN 104 -#define G4X_M_SDVO_MAX 138 -#define G4X_M1_SDVO_MIN 17 -#define G4X_M1_SDVO_MAX 23 -#define G4X_M2_SDVO_MIN 5 -#define G4X_M2_SDVO_MAX 11 -#define G4X_P_SDVO_MIN 10 -#define G4X_P_SDVO_MAX 30 -#define G4X_P1_SDVO_MIN 1 -#define G4X_P1_SDVO_MAX 3 -#define G4X_P2_SDVO_SLOW 10 -#define G4X_P2_SDVO_FAST 10 -#define G4X_P2_SDVO_LIMIT 270000 - -/*The parameter is for HDMI_DAC on G4x platform*/ -#define G4X_DOT_HDMI_DAC_MIN 22000 -#define G4X_DOT_HDMI_DAC_MAX 400000 -#define G4X_N_HDMI_DAC_MIN 1 -#define G4X_N_HDMI_DAC_MAX 4 -#define G4X_M_HDMI_DAC_MIN 104 -#define G4X_M_HDMI_DAC_MAX 138 -#define G4X_M1_HDMI_DAC_MIN 16 -#define G4X_M1_HDMI_DAC_MAX 23 -#define G4X_M2_HDMI_DAC_MIN 5 -#define G4X_M2_HDMI_DAC_MAX 11 -#define G4X_P_HDMI_DAC_MIN 5 -#define G4X_P_HDMI_DAC_MAX 80 -#define G4X_P1_HDMI_DAC_MIN 1 -#define G4X_P1_HDMI_DAC_MAX 8 -#define G4X_P2_HDMI_DAC_SLOW 10 -#define G4X_P2_HDMI_DAC_FAST 5 -#define G4X_P2_HDMI_DAC_LIMIT 165000 - -/*The parameter is for SINGLE_CHANNEL_LVDS on G4x platform*/ -#define G4X_DOT_SINGLE_CHANNEL_LVDS_MIN 20000 -#define G4X_DOT_SINGLE_CHANNEL_LVDS_MAX 115000 -#define G4X_N_SINGLE_CHANNEL_LVDS_MIN 1 -#define G4X_N_SINGLE_CHANNEL_LVDS_MAX 3 -#define G4X_M_SINGLE_CHANNEL_LVDS_MIN 104 -#define G4X_M_SINGLE_CHANNEL_LVDS_MAX 138 -#define G4X_M1_SINGLE_CHANNEL_LVDS_MIN 17 -#define G4X_M1_SINGLE_CHANNEL_LVDS_MAX 23 -#define G4X_M2_SINGLE_CHANNEL_LVDS_MIN 5 -#define G4X_M2_SINGLE_CHANNEL_LVDS_MAX 11 -#define G4X_P_SINGLE_CHANNEL_LVDS_MIN 28 -#define G4X_P_SINGLE_CHANNEL_LVDS_MAX 112 -#define G4X_P1_SINGLE_CHANNEL_LVDS_MIN 2 -#define G4X_P1_SINGLE_CHANNEL_LVDS_MAX 8 -#define G4X_P2_SINGLE_CHANNEL_LVDS_SLOW 14 -#define G4X_P2_SINGLE_CHANNEL_LVDS_FAST 14 -#define G4X_P2_SINGLE_CHANNEL_LVDS_LIMIT 0 - -/*The parameter is for DUAL_CHANNEL_LVDS on G4x platform*/ -#define G4X_DOT_DUAL_CHANNEL_LVDS_MIN 80000 -#define G4X_DOT_DUAL_CHANNEL_LVDS_MAX 224000 -#define G4X_N_DUAL_CHANNEL_LVDS_MIN 1 -#define G4X_N_DUAL_CHANNEL_LVDS_MAX 3 -#define G4X_M_DUAL_CHANNEL_LVDS_MIN 104 -#define G4X_M_DUAL_CHANNEL_LVDS_MAX 138 -#define G4X_M1_DUAL_CHANNEL_LVDS_MIN 17 -#define G4X_M1_DUAL_CHANNEL_LVDS_MAX 23 -#define G4X_M2_DUAL_CHANNEL_LVDS_MIN 5 -#define G4X_M2_DUAL_CHANNEL_LVDS_MAX 11 -#define G4X_P_DUAL_CHANNEL_LVDS_MIN 14 -#define G4X_P_DUAL_CHANNEL_LVDS_MAX 42 -#define G4X_P1_DUAL_CHANNEL_LVDS_MIN 2 -#define G4X_P1_DUAL_CHANNEL_LVDS_MAX 6 -#define G4X_P2_DUAL_CHANNEL_LVDS_SLOW 7 -#define G4X_P2_DUAL_CHANNEL_LVDS_FAST 7 -#define G4X_P2_DUAL_CHANNEL_LVDS_LIMIT 0 - -/*The parameter is for DISPLAY PORT on G4x platform*/ -#define G4X_DOT_DISPLAY_PORT_MIN 161670 -#define G4X_DOT_DISPLAY_PORT_MAX 227000 -#define G4X_N_DISPLAY_PORT_MIN 1 -#define G4X_N_DISPLAY_PORT_MAX 2 -#define G4X_M_DISPLAY_PORT_MIN 97 -#define G4X_M_DISPLAY_PORT_MAX 108 -#define G4X_M1_DISPLAY_PORT_MIN 0x10 -#define G4X_M1_DISPLAY_PORT_MAX 0x12 -#define G4X_M2_DISPLAY_PORT_MIN 0x05 -#define G4X_M2_DISPLAY_PORT_MAX 0x06 -#define G4X_P_DISPLAY_PORT_MIN 10 -#define G4X_P_DISPLAY_PORT_MAX 20 -#define G4X_P1_DISPLAY_PORT_MIN 1 -#define G4X_P1_DISPLAY_PORT_MAX 2 -#define G4X_P2_DISPLAY_PORT_SLOW 10 -#define G4X_P2_DISPLAY_PORT_FAST 10 -#define G4X_P2_DISPLAY_PORT_LIMIT 0 - -/* Ironlake / Sandybridge */ -/* as we calculate clock using (register_value + 2) for - N/M1/M2, so here the range value for them is (actual_value-2). - */ -#define IRONLAKE_DOT_MIN 25000 -#define IRONLAKE_DOT_MAX 350000 -#define IRONLAKE_VCO_MIN 1760000 -#define IRONLAKE_VCO_MAX 3510000 -#define IRONLAKE_M1_MIN 12 -#define IRONLAKE_M1_MAX 22 -#define IRONLAKE_M2_MIN 5 -#define IRONLAKE_M2_MAX 9 -#define IRONLAKE_P2_DOT_LIMIT 225000 /* 225Mhz */ - -/* We have parameter ranges for different type of outputs. */ - -/* DAC & HDMI Refclk 120Mhz */ -#define IRONLAKE_DAC_N_MIN 1 -#define IRONLAKE_DAC_N_MAX 5 -#define IRONLAKE_DAC_M_MIN 79 -#define IRONLAKE_DAC_M_MAX 127 -#define IRONLAKE_DAC_P_MIN 5 -#define IRONLAKE_DAC_P_MAX 80 -#define IRONLAKE_DAC_P1_MIN 1 -#define IRONLAKE_DAC_P1_MAX 8 -#define IRONLAKE_DAC_P2_SLOW 10 -#define IRONLAKE_DAC_P2_FAST 5 - -/* LVDS single-channel 120Mhz refclk */ -#define IRONLAKE_LVDS_S_N_MIN 1 -#define IRONLAKE_LVDS_S_N_MAX 3 -#define IRONLAKE_LVDS_S_M_MIN 79 -#define IRONLAKE_LVDS_S_M_MAX 118 -#define IRONLAKE_LVDS_S_P_MIN 28 -#define IRONLAKE_LVDS_S_P_MAX 112 -#define IRONLAKE_LVDS_S_P1_MIN 2 -#define IRONLAKE_LVDS_S_P1_MAX 8 -#define IRONLAKE_LVDS_S_P2_SLOW 14 -#define IRONLAKE_LVDS_S_P2_FAST 14 - -/* LVDS dual-channel 120Mhz refclk */ -#define IRONLAKE_LVDS_D_N_MIN 1 -#define IRONLAKE_LVDS_D_N_MAX 3 -#define IRONLAKE_LVDS_D_M_MIN 79 -#define IRONLAKE_LVDS_D_M_MAX 127 -#define IRONLAKE_LVDS_D_P_MIN 14 -#define IRONLAKE_LVDS_D_P_MAX 56 -#define IRONLAKE_LVDS_D_P1_MIN 2 -#define IRONLAKE_LVDS_D_P1_MAX 8 -#define IRONLAKE_LVDS_D_P2_SLOW 7 -#define IRONLAKE_LVDS_D_P2_FAST 7 - -/* LVDS single-channel 100Mhz refclk */ -#define IRONLAKE_LVDS_S_SSC_N_MIN 1 -#define IRONLAKE_LVDS_S_SSC_N_MAX 2 -#define IRONLAKE_LVDS_S_SSC_M_MIN 79 -#define IRONLAKE_LVDS_S_SSC_M_MAX 126 -#define IRONLAKE_LVDS_S_SSC_P_MIN 28 -#define IRONLAKE_LVDS_S_SSC_P_MAX 112 -#define IRONLAKE_LVDS_S_SSC_P1_MIN 2 -#define IRONLAKE_LVDS_S_SSC_P1_MAX 8 -#define IRONLAKE_LVDS_S_SSC_P2_SLOW 14 -#define IRONLAKE_LVDS_S_SSC_P2_FAST 14 - -/* LVDS dual-channel 100Mhz refclk */ -#define IRONLAKE_LVDS_D_SSC_N_MIN 1 -#define IRONLAKE_LVDS_D_SSC_N_MAX 3 -#define IRONLAKE_LVDS_D_SSC_M_MIN 79 -#define IRONLAKE_LVDS_D_SSC_M_MAX 126 -#define IRONLAKE_LVDS_D_SSC_P_MIN 14 -#define IRONLAKE_LVDS_D_SSC_P_MAX 42 -#define IRONLAKE_LVDS_D_SSC_P1_MIN 2 -#define IRONLAKE_LVDS_D_SSC_P1_MAX 6 -#define IRONLAKE_LVDS_D_SSC_P2_SLOW 7 -#define IRONLAKE_LVDS_D_SSC_P2_FAST 7 - -/* DisplayPort */ -#define IRONLAKE_DP_N_MIN 1 -#define IRONLAKE_DP_N_MAX 2 -#define IRONLAKE_DP_M_MIN 81 -#define IRONLAKE_DP_M_MAX 90 -#define IRONLAKE_DP_P_MIN 10 -#define IRONLAKE_DP_P_MAX 20 -#define IRONLAKE_DP_P2_FAST 10 -#define IRONLAKE_DP_P2_SLOW 10 -#define IRONLAKE_DP_P2_LIMIT 0 -#define IRONLAKE_DP_P1_MIN 1 -#define IRONLAKE_DP_P1_MAX 2 - /* FDI */ #define IRONLAKE_FDI_FREQ 2700000 /* in kHz for mode->clock */ @@ -353,292 +104,253 @@ intel_fdi_link_freq(struct drm_device *dev) } static const intel_limit_t intel_limits_i8xx_dvo = { - .dot = { .min = I8XX_DOT_MIN, .max = I8XX_DOT_MAX }, - .vco = { .min = I8XX_VCO_MIN, .max = I8XX_VCO_MAX }, - .n = { .min = I8XX_N_MIN, .max = I8XX_N_MAX }, - .m = { .min = I8XX_M_MIN, .max = I8XX_M_MAX }, - .m1 = { .min = I8XX_M1_MIN, .max = I8XX_M1_MAX }, - .m2 = { .min = I8XX_M2_MIN, .max = I8XX_M2_MAX }, - .p = { .min = I8XX_P_MIN, .max = I8XX_P_MAX }, - .p1 = { .min = I8XX_P1_MIN, .max = I8XX_P1_MAX }, - .p2 = { .dot_limit = I8XX_P2_SLOW_LIMIT, - .p2_slow = I8XX_P2_SLOW, .p2_fast = I8XX_P2_FAST }, + .dot = { .min = 25000, .max = 350000 }, + .vco = { .min = 930000, .max = 1400000 }, + .n = { .min = 3, .max = 16 }, + .m = { .min = 96, .max = 140 }, + .m1 = { .min = 18, .max = 26 }, + .m2 = { .min = 6, .max = 16 }, + .p = { .min = 4, .max = 128 }, + .p1 = { .min = 2, .max = 33 }, + .p2 = { .dot_limit = 165000, + .p2_slow = 4, .p2_fast = 2 }, .find_pll = intel_find_best_PLL, }; static const intel_limit_t intel_limits_i8xx_lvds = { - .dot = { .min = I8XX_DOT_MIN, .max = I8XX_DOT_MAX }, - .vco = { .min = I8XX_VCO_MIN, .max = I8XX_VCO_MAX }, - .n = { .min = I8XX_N_MIN, .max = I8XX_N_MAX }, - .m = { .min = I8XX_M_MIN, .max = I8XX_M_MAX }, - .m1 = { .min = I8XX_M1_MIN, .max = I8XX_M1_MAX }, - .m2 = { .min = I8XX_M2_MIN, .max = I8XX_M2_MAX }, - .p = { .min = I8XX_P_MIN, .max = I8XX_P_MAX }, - .p1 = { .min = I8XX_P1_LVDS_MIN, .max = I8XX_P1_LVDS_MAX }, - .p2 = { .dot_limit = I8XX_P2_SLOW_LIMIT, - .p2_slow = I8XX_P2_LVDS_SLOW, .p2_fast = I8XX_P2_LVDS_FAST }, + .dot = { .min = 25000, .max = 350000 }, + .vco = { .min = 930000, .max = 1400000 }, + .n = { .min = 3, .max = 16 }, + .m = { .min = 96, .max = 140 }, + .m1 = { .min = 18, .max = 26 }, + .m2 = { .min = 6, .max = 16 }, + .p = { .min = 4, .max = 128 }, + .p1 = { .min = 1, .max = 6 }, + .p2 = { .dot_limit = 165000, + .p2_slow = 14, .p2_fast = 7 }, .find_pll = intel_find_best_PLL, }; - + static const intel_limit_t intel_limits_i9xx_sdvo = { - .dot = { .min = I9XX_DOT_MIN, .max = I9XX_DOT_MAX }, - .vco = { .min = I9XX_VCO_MIN, .max = I9XX_VCO_MAX }, - .n = { .min = I9XX_N_MIN, .max = I9XX_N_MAX }, - .m = { .min = I9XX_M_MIN, .max = I9XX_M_MAX }, - .m1 = { .min = I9XX_M1_MIN, .max = I9XX_M1_MAX }, - .m2 = { .min = I9XX_M2_MIN, .max = I9XX_M2_MAX }, - .p = { .min = I9XX_P_SDVO_DAC_MIN, .max = I9XX_P_SDVO_DAC_MAX }, - .p1 = { .min = I9XX_P1_MIN, .max = I9XX_P1_MAX }, - .p2 = { .dot_limit = I9XX_P2_SDVO_DAC_SLOW_LIMIT, - .p2_slow = I9XX_P2_SDVO_DAC_SLOW, .p2_fast = I9XX_P2_SDVO_DAC_FAST }, + .dot = { .min = 20000, .max = 400000 }, + .vco = { .min = 1400000, .max = 2800000 }, + .n = { .min = 1, .max = 6 }, + .m = { .min = 70, .max = 120 }, + .m1 = { .min = 10, .max = 22 }, + .m2 = { .min = 5, .max = 9 }, + .p = { .min = 5, .max = 80 }, + .p1 = { .min = 1, .max = 8 }, + .p2 = { .dot_limit = 200000, + .p2_slow = 10, .p2_fast = 5 }, .find_pll = intel_find_best_PLL, }; static const intel_limit_t intel_limits_i9xx_lvds = { - .dot = { .min = I9XX_DOT_MIN, .max = I9XX_DOT_MAX }, - .vco = { .min = I9XX_VCO_MIN, .max = I9XX_VCO_MAX }, - .n = { .min = I9XX_N_MIN, .max = I9XX_N_MAX }, - .m = { .min = I9XX_M_MIN, .max = I9XX_M_MAX }, - .m1 = { .min = I9XX_M1_MIN, .max = I9XX_M1_MAX }, - .m2 = { .min = I9XX_M2_MIN, .max = I9XX_M2_MAX }, - .p = { .min = I9XX_P_LVDS_MIN, .max = I9XX_P_LVDS_MAX }, - .p1 = { .min = I9XX_P1_MIN, .max = I9XX_P1_MAX }, - /* The single-channel range is 25-112Mhz, and dual-channel - * is 80-224Mhz. Prefer single channel as much as possible. - */ - .p2 = { .dot_limit = I9XX_P2_LVDS_SLOW_LIMIT, - .p2_slow = I9XX_P2_LVDS_SLOW, .p2_fast = I9XX_P2_LVDS_FAST }, + .dot = { .min = 20000, .max = 400000 }, + .vco = { .min = 1400000, .max = 2800000 }, + .n = { .min = 1, .max = 6 }, + .m = { .min = 70, .max = 120 }, + .m1 = { .min = 10, .max = 22 }, + .m2 = { .min = 5, .max = 9 }, + .p = { .min = 7, .max = 98 }, + .p1 = { .min = 1, .max = 8 }, + .p2 = { .dot_limit = 112000, + .p2_slow = 14, .p2_fast = 7 }, .find_pll = intel_find_best_PLL, }; - /* below parameter and function is for G4X Chipset Family*/ + static const intel_limit_t intel_limits_g4x_sdvo = { - .dot = { .min = G4X_DOT_SDVO_MIN, .max = G4X_DOT_SDVO_MAX }, - .vco = { .min = G4X_VCO_MIN, .max = G4X_VCO_MAX}, - .n = { .min = G4X_N_SDVO_MIN, .max = G4X_N_SDVO_MAX }, - .m = { .min = G4X_M_SDVO_MIN, .max = G4X_M_SDVO_MAX }, - .m1 = { .min = G4X_M1_SDVO_MIN, .max = G4X_M1_SDVO_MAX }, - .m2 = { .min = G4X_M2_SDVO_MIN, .max = G4X_M2_SDVO_MAX }, - .p = { .min = G4X_P_SDVO_MIN, .max = G4X_P_SDVO_MAX }, - .p1 = { .min = G4X_P1_SDVO_MIN, .max = G4X_P1_SDVO_MAX}, - .p2 = { .dot_limit = G4X_P2_SDVO_LIMIT, - .p2_slow = G4X_P2_SDVO_SLOW, - .p2_fast = G4X_P2_SDVO_FAST + .dot = { .min = 25000, .max = 270000 }, + .vco = { .min = 1750000, .max = 3500000}, + .n = { .min = 1, .max = 4 }, + .m = { .min = 104, .max = 138 }, + .m1 = { .min = 17, .max = 23 }, + .m2 = { .min = 5, .max = 11 }, + .p = { .min = 10, .max = 30 }, + .p1 = { .min = 1, .max = 3}, + .p2 = { .dot_limit = 270000, + .p2_slow = 10, + .p2_fast = 10 }, .find_pll = intel_g4x_find_best_PLL, }; static const intel_limit_t intel_limits_g4x_hdmi = { - .dot = { .min = G4X_DOT_HDMI_DAC_MIN, .max = G4X_DOT_HDMI_DAC_MAX }, - .vco = { .min = G4X_VCO_MIN, .max = G4X_VCO_MAX}, - .n = { .min = G4X_N_HDMI_DAC_MIN, .max = G4X_N_HDMI_DAC_MAX }, - .m = { .min = G4X_M_HDMI_DAC_MIN, .max = G4X_M_HDMI_DAC_MAX }, - .m1 = { .min = G4X_M1_HDMI_DAC_MIN, .max = G4X_M1_HDMI_DAC_MAX }, - .m2 = { .min = G4X_M2_HDMI_DAC_MIN, .max = G4X_M2_HDMI_DAC_MAX }, - .p = { .min = G4X_P_HDMI_DAC_MIN, .max = G4X_P_HDMI_DAC_MAX }, - .p1 = { .min = G4X_P1_HDMI_DAC_MIN, .max = G4X_P1_HDMI_DAC_MAX}, - .p2 = { .dot_limit = G4X_P2_HDMI_DAC_LIMIT, - .p2_slow = G4X_P2_HDMI_DAC_SLOW, - .p2_fast = G4X_P2_HDMI_DAC_FAST - }, + .dot = { .min = 22000, .max = 400000 }, + .vco = { .min = 1750000, .max = 3500000}, + .n = { .min = 1, .max = 4 }, + .m = { .min = 104, .max = 138 }, + .m1 = { .min = 16, .max = 23 }, + .m2 = { .min = 5, .max = 11 }, + .p = { .min = 5, .max = 80 }, + .p1 = { .min = 1, .max = 8}, + .p2 = { .dot_limit = 165000, + .p2_slow = 10, .p2_fast = 5 }, .find_pll = intel_g4x_find_best_PLL, }; static const intel_limit_t intel_limits_g4x_single_channel_lvds = { - .dot = { .min = G4X_DOT_SINGLE_CHANNEL_LVDS_MIN, - .max = G4X_DOT_SINGLE_CHANNEL_LVDS_MAX }, - .vco = { .min = G4X_VCO_MIN, - .max = G4X_VCO_MAX }, - .n = { .min = G4X_N_SINGLE_CHANNEL_LVDS_MIN, - .max = G4X_N_SINGLE_CHANNEL_LVDS_MAX }, - .m = { .min = G4X_M_SINGLE_CHANNEL_LVDS_MIN, - .max = G4X_M_SINGLE_CHANNEL_LVDS_MAX }, - .m1 = { .min = G4X_M1_SINGLE_CHANNEL_LVDS_MIN, - .max = G4X_M1_SINGLE_CHANNEL_LVDS_MAX }, - .m2 = { .min = G4X_M2_SINGLE_CHANNEL_LVDS_MIN, - .max = G4X_M2_SINGLE_CHANNEL_LVDS_MAX }, - .p = { .min = G4X_P_SINGLE_CHANNEL_LVDS_MIN, - .max = G4X_P_SINGLE_CHANNEL_LVDS_MAX }, - .p1 = { .min = G4X_P1_SINGLE_CHANNEL_LVDS_MIN, - .max = G4X_P1_SINGLE_CHANNEL_LVDS_MAX }, - .p2 = { .dot_limit = G4X_P2_SINGLE_CHANNEL_LVDS_LIMIT, - .p2_slow = G4X_P2_SINGLE_CHANNEL_LVDS_SLOW, - .p2_fast = G4X_P2_SINGLE_CHANNEL_LVDS_FAST + .dot = { .min = 20000, .max = 115000 }, + .vco = { .min = 1750000, .max = 3500000 }, + .n = { .min = 1, .max = 3 }, + .m = { .min = 104, .max = 138 }, + .m1 = { .min = 17, .max = 23 }, + .m2 = { .min = 5, .max = 11 }, + .p = { .min = 28, .max = 112 }, + .p1 = { .min = 2, .max = 8 }, + .p2 = { .dot_limit = 0, + .p2_slow = 14, .p2_fast = 14 }, .find_pll = intel_g4x_find_best_PLL, }; static const intel_limit_t intel_limits_g4x_dual_channel_lvds = { - .dot = { .min = G4X_DOT_DUAL_CHANNEL_LVDS_MIN, - .max = G4X_DOT_DUAL_CHANNEL_LVDS_MAX }, - .vco = { .min = G4X_VCO_MIN, - .max = G4X_VCO_MAX }, - .n = { .min = G4X_N_DUAL_CHANNEL_LVDS_MIN, - .max = G4X_N_DUAL_CHANNEL_LVDS_MAX }, - .m = { .min = G4X_M_DUAL_CHANNEL_LVDS_MIN, - .max = G4X_M_DUAL_CHANNEL_LVDS_MAX }, - .m1 = { .min = G4X_M1_DUAL_CHANNEL_LVDS_MIN, - .max = G4X_M1_DUAL_CHANNEL_LVDS_MAX }, - .m2 = { .min = G4X_M2_DUAL_CHANNEL_LVDS_MIN, - .max = G4X_M2_DUAL_CHANNEL_LVDS_MAX }, - .p = { .min = G4X_P_DUAL_CHANNEL_LVDS_MIN, - .max = G4X_P_DUAL_CHANNEL_LVDS_MAX }, - .p1 = { .min = G4X_P1_DUAL_CHANNEL_LVDS_MIN, - .max = G4X_P1_DUAL_CHANNEL_LVDS_MAX }, - .p2 = { .dot_limit = G4X_P2_DUAL_CHANNEL_LVDS_LIMIT, - .p2_slow = G4X_P2_DUAL_CHANNEL_LVDS_SLOW, - .p2_fast = G4X_P2_DUAL_CHANNEL_LVDS_FAST + .dot = { .min = 80000, .max = 224000 }, + .vco = { .min = 1750000, .max = 3500000 }, + .n = { .min = 1, .max = 3 }, + .m = { .min = 104, .max = 138 }, + .m1 = { .min = 17, .max = 23 }, + .m2 = { .min = 5, .max = 11 }, + .p = { .min = 14, .max = 42 }, + .p1 = { .min = 2, .max = 6 }, + .p2 = { .dot_limit = 0, + .p2_slow = 7, .p2_fast = 7 }, .find_pll = intel_g4x_find_best_PLL, }; static const intel_limit_t intel_limits_g4x_display_port = { - .dot = { .min = G4X_DOT_DISPLAY_PORT_MIN, - .max = G4X_DOT_DISPLAY_PORT_MAX }, - .vco = { .min = G4X_VCO_MIN, - .max = G4X_VCO_MAX}, - .n = { .min = G4X_N_DISPLAY_PORT_MIN, - .max = G4X_N_DISPLAY_PORT_MAX }, - .m = { .min = G4X_M_DISPLAY_PORT_MIN, - .max = G4X_M_DISPLAY_PORT_MAX }, - .m1 = { .min = G4X_M1_DISPLAY_PORT_MIN, - .max = G4X_M1_DISPLAY_PORT_MAX }, - .m2 = { .min = G4X_M2_DISPLAY_PORT_MIN, - .max = G4X_M2_DISPLAY_PORT_MAX }, - .p = { .min = G4X_P_DISPLAY_PORT_MIN, - .max = G4X_P_DISPLAY_PORT_MAX }, - .p1 = { .min = G4X_P1_DISPLAY_PORT_MIN, - .max = G4X_P1_DISPLAY_PORT_MAX}, - .p2 = { .dot_limit = G4X_P2_DISPLAY_PORT_LIMIT, - .p2_slow = G4X_P2_DISPLAY_PORT_SLOW, - .p2_fast = G4X_P2_DISPLAY_PORT_FAST }, + .dot = { .min = 161670, .max = 227000 }, + .vco = { .min = 1750000, .max = 3500000}, + .n = { .min = 1, .max = 2 }, + .m = { .min = 97, .max = 108 }, + .m1 = { .min = 0x10, .max = 0x12 }, + .m2 = { .min = 0x05, .max = 0x06 }, + .p = { .min = 10, .max = 20 }, + .p1 = { .min = 1, .max = 2}, + .p2 = { .dot_limit = 0, + .p2_slow = 10, .p2_fast = 10 }, .find_pll = intel_find_pll_g4x_dp, }; static const intel_limit_t intel_limits_pineview_sdvo = { - .dot = { .min = I9XX_DOT_MIN, .max = I9XX_DOT_MAX}, - .vco = { .min = PINEVIEW_VCO_MIN, .max = PINEVIEW_VCO_MAX }, - .n = { .min = PINEVIEW_N_MIN, .max = PINEVIEW_N_MAX }, - .m = { .min = PINEVIEW_M_MIN, .max = PINEVIEW_M_MAX }, - .m1 = { .min = PINEVIEW_M1_MIN, .max = PINEVIEW_M1_MAX }, - .m2 = { .min = PINEVIEW_M2_MIN, .max = PINEVIEW_M2_MAX }, - .p = { .min = I9XX_P_SDVO_DAC_MIN, .max = I9XX_P_SDVO_DAC_MAX }, - .p1 = { .min = I9XX_P1_MIN, .max = I9XX_P1_MAX }, - .p2 = { .dot_limit = I9XX_P2_SDVO_DAC_SLOW_LIMIT, - .p2_slow = I9XX_P2_SDVO_DAC_SLOW, .p2_fast = I9XX_P2_SDVO_DAC_FAST }, + .dot = { .min = 20000, .max = 400000}, + .vco = { .min = 1700000, .max = 3500000 }, + /* Pineview's Ncounter is a ring counter */ + .n = { .min = 3, .max = 6 }, + .m = { .min = 2, .max = 256 }, + /* Pineview only has one combined m divider, which we treat as m2. */ + .m1 = { .min = 0, .max = 0 }, + .m2 = { .min = 0, .max = 254 }, + .p = { .min = 5, .max = 80 }, + .p1 = { .min = 1, .max = 8 }, + .p2 = { .dot_limit = 200000, + .p2_slow = 10, .p2_fast = 5 }, .find_pll = intel_find_best_PLL, }; static const intel_limit_t intel_limits_pineview_lvds = { - .dot = { .min = I9XX_DOT_MIN, .max = I9XX_DOT_MAX }, - .vco = { .min = PINEVIEW_VCO_MIN, .max = PINEVIEW_VCO_MAX }, - .n = { .min = PINEVIEW_N_MIN, .max = PINEVIEW_N_MAX }, - .m = { .min = PINEVIEW_M_MIN, .max = PINEVIEW_M_MAX }, - .m1 = { .min = PINEVIEW_M1_MIN, .max = PINEVIEW_M1_MAX }, - .m2 = { .min = PINEVIEW_M2_MIN, .max = PINEVIEW_M2_MAX }, - .p = { .min = PINEVIEW_P_LVDS_MIN, .max = PINEVIEW_P_LVDS_MAX }, - .p1 = { .min = I9XX_P1_MIN, .max = I9XX_P1_MAX }, - /* Pineview only supports single-channel mode. */ - .p2 = { .dot_limit = I9XX_P2_LVDS_SLOW_LIMIT, - .p2_slow = I9XX_P2_LVDS_SLOW, .p2_fast = I9XX_P2_LVDS_SLOW }, + .dot = { .min = 20000, .max = 400000 }, + .vco = { .min = 1700000, .max = 3500000 }, + .n = { .min = 3, .max = 6 }, + .m = { .min = 2, .max = 256 }, + .m1 = { .min = 0, .max = 0 }, + .m2 = { .min = 0, .max = 254 }, + .p = { .min = 7, .max = 112 }, + .p1 = { .min = 1, .max = 8 }, + .p2 = { .dot_limit = 112000, + .p2_slow = 14, .p2_fast = 14 }, .find_pll = intel_find_best_PLL, }; +/* Ironlake / Sandybridge + * + * We calculate clock using (register_value + 2) for N/M1/M2, so here + * the range value for them is (actual_value - 2). + */ static const intel_limit_t intel_limits_ironlake_dac = { - .dot = { .min = IRONLAKE_DOT_MIN, .max = IRONLAKE_DOT_MAX }, - .vco = { .min = IRONLAKE_VCO_MIN, .max = IRONLAKE_VCO_MAX }, - .n = { .min = IRONLAKE_DAC_N_MIN, .max = IRONLAKE_DAC_N_MAX }, - .m = { .min = IRONLAKE_DAC_M_MIN, .max = IRONLAKE_DAC_M_MAX }, - .m1 = { .min = IRONLAKE_M1_MIN, .max = IRONLAKE_M1_MAX }, - .m2 = { .min = IRONLAKE_M2_MIN, .max = IRONLAKE_M2_MAX }, - .p = { .min = IRONLAKE_DAC_P_MIN, .max = IRONLAKE_DAC_P_MAX }, - .p1 = { .min = IRONLAKE_DAC_P1_MIN, .max = IRONLAKE_DAC_P1_MAX }, - .p2 = { .dot_limit = IRONLAKE_P2_DOT_LIMIT, - .p2_slow = IRONLAKE_DAC_P2_SLOW, - .p2_fast = IRONLAKE_DAC_P2_FAST }, + .dot = { .min = 25000, .max = 350000 }, + .vco = { .min = 1760000, .max = 3510000 }, + .n = { .min = 1, .max = 5 }, + .m = { .min = 79, .max = 127 }, + .m1 = { .min = 12, .max = 22 }, + .m2 = { .min = 5, .max = 9 }, + .p = { .min = 5, .max = 80 }, + .p1 = { .min = 1, .max = 8 }, + .p2 = { .dot_limit = 225000, + .p2_slow = 10, .p2_fast = 5 }, .find_pll = intel_g4x_find_best_PLL, }; static const intel_limit_t intel_limits_ironlake_single_lvds = { - .dot = { .min = IRONLAKE_DOT_MIN, .max = IRONLAKE_DOT_MAX }, - .vco = { .min = IRONLAKE_VCO_MIN, .max = IRONLAKE_VCO_MAX }, - .n = { .min = IRONLAKE_LVDS_S_N_MIN, .max = IRONLAKE_LVDS_S_N_MAX }, - .m = { .min = IRONLAKE_LVDS_S_M_MIN, .max = IRONLAKE_LVDS_S_M_MAX }, - .m1 = { .min = IRONLAKE_M1_MIN, .max = IRONLAKE_M1_MAX }, - .m2 = { .min = IRONLAKE_M2_MIN, .max = IRONLAKE_M2_MAX }, - .p = { .min = IRONLAKE_LVDS_S_P_MIN, .max = IRONLAKE_LVDS_S_P_MAX }, - .p1 = { .min = IRONLAKE_LVDS_S_P1_MIN, .max = IRONLAKE_LVDS_S_P1_MAX }, - .p2 = { .dot_limit = IRONLAKE_P2_DOT_LIMIT, - .p2_slow = IRONLAKE_LVDS_S_P2_SLOW, - .p2_fast = IRONLAKE_LVDS_S_P2_FAST }, + .dot = { .min = 25000, .max = 350000 }, + .vco = { .min = 1760000, .max = 3510000 }, + .n = { .min = 1, .max = 3 }, + .m = { .min = 79, .max = 118 }, + .m1 = { .min = 12, .max = 22 }, + .m2 = { .min = 5, .max = 9 }, + .p = { .min = 28, .max = 112 }, + .p1 = { .min = 2, .max = 8 }, + .p2 = { .dot_limit = 225000, + .p2_slow = 14, .p2_fast = 14 }, .find_pll = intel_g4x_find_best_PLL, }; static const intel_limit_t intel_limits_ironlake_dual_lvds = { - .dot = { .min = IRONLAKE_DOT_MIN, .max = IRONLAKE_DOT_MAX }, - .vco = { .min = IRONLAKE_VCO_MIN, .max = IRONLAKE_VCO_MAX }, - .n = { .min = IRONLAKE_LVDS_D_N_MIN, .max = IRONLAKE_LVDS_D_N_MAX }, - .m = { .min = IRONLAKE_LVDS_D_M_MIN, .max = IRONLAKE_LVDS_D_M_MAX }, - .m1 = { .min = IRONLAKE_M1_MIN, .max = IRONLAKE_M1_MAX }, - .m2 = { .min = IRONLAKE_M2_MIN, .max = IRONLAKE_M2_MAX }, - .p = { .min = IRONLAKE_LVDS_D_P_MIN, .max = IRONLAKE_LVDS_D_P_MAX }, - .p1 = { .min = IRONLAKE_LVDS_D_P1_MIN, .max = IRONLAKE_LVDS_D_P1_MAX }, - .p2 = { .dot_limit = IRONLAKE_P2_DOT_LIMIT, - .p2_slow = IRONLAKE_LVDS_D_P2_SLOW, - .p2_fast = IRONLAKE_LVDS_D_P2_FAST }, + .dot = { .min = 25000, .max = 350000 }, + .vco = { .min = 1760000, .max = 3510000 }, + .n = { .min = 1, .max = 3 }, + .m = { .min = 79, .max = 127 }, + .m1 = { .min = 12, .max = 22 }, + .m2 = { .min = 5, .max = 9 }, + .p = { .min = 14, .max = 56 }, + .p1 = { .min = 2, .max = 8 }, + .p2 = { .dot_limit = 225000, + .p2_slow = 7, .p2_fast = 7 }, .find_pll = intel_g4x_find_best_PLL, }; +/* LVDS 100mhz refclk limits. */ static const intel_limit_t intel_limits_ironlake_single_lvds_100m = { - .dot = { .min = IRONLAKE_DOT_MIN, .max = IRONLAKE_DOT_MAX }, - .vco = { .min = IRONLAKE_VCO_MIN, .max = IRONLAKE_VCO_MAX }, - .n = { .min = IRONLAKE_LVDS_S_SSC_N_MIN, .max = IRONLAKE_LVDS_S_SSC_N_MAX }, - .m = { .min = IRONLAKE_LVDS_S_SSC_M_MIN, .max = IRONLAKE_LVDS_S_SSC_M_MAX }, - .m1 = { .min = IRONLAKE_M1_MIN, .max = IRONLAKE_M1_MAX }, - .m2 = { .min = IRONLAKE_M2_MIN, .max = IRONLAKE_M2_MAX }, - .p = { .min = IRONLAKE_LVDS_S_SSC_P_MIN, .max = IRONLAKE_LVDS_S_SSC_P_MAX }, - .p1 = { .min = IRONLAKE_LVDS_S_SSC_P1_MIN,.max = IRONLAKE_LVDS_S_SSC_P1_MAX }, - .p2 = { .dot_limit = IRONLAKE_P2_DOT_LIMIT, - .p2_slow = IRONLAKE_LVDS_S_SSC_P2_SLOW, - .p2_fast = IRONLAKE_LVDS_S_SSC_P2_FAST }, + .dot = { .min = 25000, .max = 350000 }, + .vco = { .min = 1760000, .max = 3510000 }, + .n = { .min = 1, .max = 2 }, + .m = { .min = 79, .max = 126 }, + .m1 = { .min = 12, .max = 22 }, + .m2 = { .min = 5, .max = 9 }, + .p = { .min = 28, .max = 112 }, + .p1 = { .min = 2,.max = 8 }, + .p2 = { .dot_limit = 225000, + .p2_slow = 14, .p2_fast = 14 }, .find_pll = intel_g4x_find_best_PLL, }; static const intel_limit_t intel_limits_ironlake_dual_lvds_100m = { - .dot = { .min = IRONLAKE_DOT_MIN, .max = IRONLAKE_DOT_MAX }, - .vco = { .min = IRONLAKE_VCO_MIN, .max = IRONLAKE_VCO_MAX }, - .n = { .min = IRONLAKE_LVDS_D_SSC_N_MIN, .max = IRONLAKE_LVDS_D_SSC_N_MAX }, - .m = { .min = IRONLAKE_LVDS_D_SSC_M_MIN, .max = IRONLAKE_LVDS_D_SSC_M_MAX }, - .m1 = { .min = IRONLAKE_M1_MIN, .max = IRONLAKE_M1_MAX }, - .m2 = { .min = IRONLAKE_M2_MIN, .max = IRONLAKE_M2_MAX }, - .p = { .min = IRONLAKE_LVDS_D_SSC_P_MIN, .max = IRONLAKE_LVDS_D_SSC_P_MAX }, - .p1 = { .min = IRONLAKE_LVDS_D_SSC_P1_MIN,.max = IRONLAKE_LVDS_D_SSC_P1_MAX }, - .p2 = { .dot_limit = IRONLAKE_P2_DOT_LIMIT, - .p2_slow = IRONLAKE_LVDS_D_SSC_P2_SLOW, - .p2_fast = IRONLAKE_LVDS_D_SSC_P2_FAST }, + .dot = { .min = 25000, .max = 350000 }, + .vco = { .min = 1760000, .max = 3510000 }, + .n = { .min = 1, .max = 3 }, + .m = { .min = 79, .max = 126 }, + .m1 = { .min = 12, .max = 22 }, + .m2 = { .min = 5, .max = 9 }, + .p = { .min = 14, .max = 42 }, + .p1 = { .min = 2,.max = 6 }, + .p2 = { .dot_limit = 225000, + .p2_slow = 7, .p2_fast = 7 }, .find_pll = intel_g4x_find_best_PLL, }; static const intel_limit_t intel_limits_ironlake_display_port = { - .dot = { .min = IRONLAKE_DOT_MIN, - .max = IRONLAKE_DOT_MAX }, - .vco = { .min = IRONLAKE_VCO_MIN, - .max = IRONLAKE_VCO_MAX}, - .n = { .min = IRONLAKE_DP_N_MIN, - .max = IRONLAKE_DP_N_MAX }, - .m = { .min = IRONLAKE_DP_M_MIN, - .max = IRONLAKE_DP_M_MAX }, - .m1 = { .min = IRONLAKE_M1_MIN, - .max = IRONLAKE_M1_MAX }, - .m2 = { .min = IRONLAKE_M2_MIN, - .max = IRONLAKE_M2_MAX }, - .p = { .min = IRONLAKE_DP_P_MIN, - .max = IRONLAKE_DP_P_MAX }, - .p1 = { .min = IRONLAKE_DP_P1_MIN, - .max = IRONLAKE_DP_P1_MAX}, - .p2 = { .dot_limit = IRONLAKE_DP_P2_LIMIT, - .p2_slow = IRONLAKE_DP_P2_SLOW, - .p2_fast = IRONLAKE_DP_P2_FAST }, + .dot = { .min = 25000, .max = 350000 }, + .vco = { .min = 1760000, .max = 3510000}, + .n = { .min = 1, .max = 2 }, + .m = { .min = 81, .max = 90 }, + .m1 = { .min = 12, .max = 22 }, + .m2 = { .min = 5, .max = 9 }, + .p = { .min = 10, .max = 20 }, + .p1 = { .min = 1, .max = 2}, + .p2 = { .dot_limit = 0, + .p2_slow = 10, .p2_fast = 10 }, .find_pll = intel_find_pll_ironlake_dp, }; -- cgit v1.1 From 2c34b850ee1e9f86b41706149d0954eee58757a3 Mon Sep 17 00:00:00 2001 From: Ben Widawsky Date: Sat, 19 Mar 2011 18:14:26 -0700 Subject: drm/i915: fix ilk rc6 teardown locking In the failure cases during rc6 initialization, both the power context and render context may get !refcount without holding struct_mutex. However, on rc6 disabling, the lock is held by the caller. Rearranged the locking so that it's safe in both cases. Signed-off-by: Ben Widawsky Signed-off-by: Chris Wilson Reviewed-by: Keith Packard Signed-off-by: Keith Packard --- drivers/gpu/drm/i915/intel_display.c | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) (limited to 'drivers/gpu/drm/i915/intel_display.c') diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c index bcef1c1..b6f593a 100644 --- a/drivers/gpu/drm/i915/intel_display.c +++ b/drivers/gpu/drm/i915/intel_display.c @@ -6713,13 +6713,14 @@ intel_alloc_context_page(struct drm_device *dev) struct drm_i915_gem_object *ctx; int ret; + WARN_ON(!mutex_is_locked(&dev->struct_mutex)); + ctx = i915_gem_alloc_object(dev, 4096); if (!ctx) { DRM_DEBUG("failed to alloc power context, RC6 disabled\n"); return NULL; } - mutex_lock(&dev->struct_mutex); ret = i915_gem_object_pin(ctx, 4096, true); if (ret) { DRM_ERROR("failed to pin power context: %d\n", ret); @@ -6731,7 +6732,6 @@ intel_alloc_context_page(struct drm_device *dev) DRM_ERROR("failed to set-domain on power context: %d\n", ret); goto err_unpin; } - mutex_unlock(&dev->struct_mutex); return ctx; @@ -7295,9 +7295,12 @@ void ironlake_enable_rc6(struct drm_device *dev) if (!i915_enable_rc6) return; + mutex_lock(&dev->struct_mutex); ret = ironlake_setup_rc6(dev); - if (ret) + if (ret) { + mutex_unlock(&dev->struct_mutex); return; + } /* * GPU can automatically power down the render unit if given a page @@ -7306,6 +7309,7 @@ void ironlake_enable_rc6(struct drm_device *dev) ret = BEGIN_LP_RING(6); if (ret) { ironlake_teardown_rc6(dev); + mutex_unlock(&dev->struct_mutex); return; } @@ -7323,6 +7327,7 @@ void ironlake_enable_rc6(struct drm_device *dev) I915_WRITE(PWRCTXA, dev_priv->pwrctx->gtt_offset | PWRCTX_EN); I915_WRITE(RSTDBYCTL, I915_READ(RSTDBYCTL) & ~RCX_SW_EXIT); + mutex_unlock(&dev->struct_mutex); } -- cgit v1.1 From 4a246cfc3c337ecb800d508ee5ed906534edb25c Mon Sep 17 00:00:00 2001 From: Ben Widawsky Date: Sat, 19 Mar 2011 18:14:28 -0700 Subject: drm/i915: fix rc6 initialization on Ironlake There is a race condition between setting PWRCTXA and executing MI_SET_CONTEXT. PWRCTXA must not be set until a valid context has been written (or else the GPU could possible go into rc6, and return to an invalid context). Reported-and-Tested-by: Gu Rui Bugzilla: https://bugzilla.kernel.org/show_bug.cgi?id=28582 Signed-off-by: Ben Widawsky Signed-off-by: Chris Wilson Signed-off-by: Keith Packard --- drivers/gpu/drm/i915/intel_display.c | 13 +++++++++++++ 1 file changed, 13 insertions(+) (limited to 'drivers/gpu/drm/i915/intel_display.c') diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c index b6f593a..463f753 100644 --- a/drivers/gpu/drm/i915/intel_display.c +++ b/drivers/gpu/drm/i915/intel_display.c @@ -7325,6 +7325,19 @@ void ironlake_enable_rc6(struct drm_device *dev) OUT_RING(MI_FLUSH); ADVANCE_LP_RING(); + /* + * Wait for the command parser to advance past MI_SET_CONTEXT. The HW + * does an implicit flush, combined with MI_FLUSH above, it should be + * safe to assume that renderctx is valid + */ + ret = intel_wait_ring_idle(LP_RING(dev_priv)); + if (ret) { + DRM_ERROR("failed to enable ironlake power power savings\n"); + ironlake_teardown_rc6(dev); + mutex_unlock(&dev->struct_mutex); + return; + } + I915_WRITE(PWRCTXA, dev_priv->pwrctx->gtt_offset | PWRCTX_EN); I915_WRITE(RSTDBYCTL, I915_READ(RSTDBYCTL) & ~RCX_SW_EXIT); mutex_unlock(&dev->struct_mutex); -- cgit v1.1 From 7df8721beb9cbd849dce2b153e3b287c98adbb7f Mon Sep 17 00:00:00 2001 From: Jesse Barnes Date: Wed, 30 Mar 2011 14:08:56 -0700 Subject: drm/i915: use i915_enable_rc6 on SNB too For debug & testing. Signed-off-by: Jesse Barnes Reviewed-by: Ben Widawsky Signed-off-by: Chris Wilson --- drivers/gpu/drm/i915/intel_display.c | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) (limited to 'drivers/gpu/drm/i915/intel_display.c') diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c index 463f753..e99ae3b 100644 --- a/drivers/gpu/drm/i915/intel_display.c +++ b/drivers/gpu/drm/i915/intel_display.c @@ -6959,7 +6959,7 @@ void gen6_enable_rps(struct drm_i915_private *dev_priv) { u32 rp_state_cap = I915_READ(GEN6_RP_STATE_CAP); u32 gt_perf_status = I915_READ(GEN6_GT_PERF_STATUS); - u32 pcu_mbox; + u32 pcu_mbox, rc6_mask = 0; int cur_freq, min_freq, max_freq; int i; @@ -6990,9 +6990,12 @@ void gen6_enable_rps(struct drm_i915_private *dev_priv) I915_WRITE(GEN6_RC6p_THRESHOLD, 100000); I915_WRITE(GEN6_RC6pp_THRESHOLD, 64000); /* unused */ + if (i915_enable_rc6) + rc6_mask = GEN6_RC_CTL_RC6p_ENABLE | + GEN6_RC_CTL_RC6_ENABLE; + I915_WRITE(GEN6_RC_CONTROL, - GEN6_RC_CTL_RC6p_ENABLE | - GEN6_RC_CTL_RC6_ENABLE | + rc6_mask | GEN6_RC_CTL_EI_MODE(1) | GEN6_RC_CTL_HW_ENABLE); -- cgit v1.1 From 2c7111dbaec72b01c804afb8ad77c6c7523986fd Mon Sep 17 00:00:00 2001 From: Chris Wilson Date: Tue, 29 Mar 2011 10:40:27 +0100 Subject: drm/i915: Disable all outputs early, before KMS takeover If the outputs are active and continuing to access the GATT when we teardown the PTEs, then there is a potential for us to hang the GPU. The hang tends to be a PGTBL_ER with either an invalid host access or an invalid display plane fetch. v2: Reorder IRQ initialisation to defer until after GEM is setup. Reported-by: Pekka Enberg Signed-off-by: Chris Wilson Tested-by: Daniel Vetter (855GM) Tested-by: Pekka Enberg # note that this doesn't fix the underlying problem of the PGTBL_ER and pipe underruns being reported immediately upon init on his 965GM MacBook Reported-and-tested-by: Rick Bramley Bugzilla: https://bugs.freedesktop.org/show_bug.cgi?id=35635 Reported-and-tested-by: Zdenek Kabelac Bugzilla: https://bugs.freedesktop.org/show_bug.cgi?id=36048 Reviewed-by: Ben Widawsky --- drivers/gpu/drm/i915/intel_display.c | 17 +++++++++++------ 1 file changed, 11 insertions(+), 6 deletions(-) (limited to 'drivers/gpu/drm/i915/intel_display.c') diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c index e99ae3b..a38fb39 100644 --- a/drivers/gpu/drm/i915/intel_display.c +++ b/drivers/gpu/drm/i915/intel_display.c @@ -6627,6 +6627,9 @@ static void intel_setup_outputs(struct drm_device *dev) } intel_panel_setup_backlight(dev); + + /* disable all the possible outputs/crtcs before entering KMS mode */ + drm_helper_disable_unused_functions(dev); } static void intel_user_framebuffer_destroy(struct drm_framebuffer *fb) @@ -7573,13 +7576,12 @@ void intel_modeset_init(struct drm_device *dev) intel_crtc_init(dev, i); } + /* Just disable it once at startup */ + i915_disable_vga(dev); intel_setup_outputs(dev); intel_enable_clock_gating(dev); - /* Just disable it once at startup */ - i915_disable_vga(dev); - if (IS_IRONLAKE_M(dev)) { ironlake_enable_drps(dev); intel_init_emon(dev); @@ -7588,12 +7590,15 @@ void intel_modeset_init(struct drm_device *dev) if (IS_GEN6(dev)) gen6_enable_rps(dev_priv); - if (IS_IRONLAKE_M(dev)) - ironlake_enable_rc6(dev); - INIT_WORK(&dev_priv->idle_work, intel_idle_update); setup_timer(&dev_priv->idle_timer, intel_gpu_idle_timer, (unsigned long)dev); +} + +void intel_modeset_gem_init(struct drm_device *dev) +{ + if (IS_IRONLAKE_M(dev)) + ironlake_enable_rc6(dev); intel_setup_overlay(dev); } -- cgit v1.1 From fcca7926299944841569515da321bef9655b7703 Mon Sep 17 00:00:00 2001 From: Ben Widawsky Date: Mon, 25 Apr 2011 11:23:07 -0700 Subject: drm/i915: reference counted forcewake Provide a reference count to track the forcewake state of the GPU and give a safe mechanism for userspace to wake the GT. This also potentially saves a UC read if the GT is known to be awake already. The reference count is atomic, but the register access and hardware wake sequence is protected by struct_mutex. Signed-off-by: Ben Widawsky Signed-off-by: Chris Wilson --- drivers/gpu/drm/i915/intel_display.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'drivers/gpu/drm/i915/intel_display.c') diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c index a38fb39..220c3e0 100644 --- a/drivers/gpu/drm/i915/intel_display.c +++ b/drivers/gpu/drm/i915/intel_display.c @@ -1540,7 +1540,7 @@ static void sandybridge_blit_fbc_update(struct drm_device *dev) u32 blt_ecoskpd; /* Make sure blitter notifies FBC of writes */ - __gen6_gt_force_wake_get(dev_priv); + gen6_gt_force_wake_get(dev_priv); blt_ecoskpd = I915_READ(GEN6_BLITTER_ECOSKPD); blt_ecoskpd |= GEN6_BLITTER_FBC_NOTIFY << GEN6_BLITTER_LOCK_SHIFT; @@ -1551,7 +1551,7 @@ static void sandybridge_blit_fbc_update(struct drm_device *dev) GEN6_BLITTER_LOCK_SHIFT); I915_WRITE(GEN6_BLITTER_ECOSKPD, blt_ecoskpd); POSTING_READ(GEN6_BLITTER_ECOSKPD); - __gen6_gt_force_wake_put(dev_priv); + gen6_gt_force_wake_put(dev_priv); } static void ironlake_enable_fbc(struct drm_crtc *crtc, unsigned long interval) @@ -6973,7 +6973,7 @@ void gen6_enable_rps(struct drm_i915_private *dev_priv) * userspace... */ I915_WRITE(GEN6_RC_STATE, 0); - __gen6_gt_force_wake_get(dev_priv); + gen6_gt_force_wake_get(dev_priv); /* disable the counters and set deterministic thresholds */ I915_WRITE(GEN6_RC_CONTROL, 0); @@ -7074,7 +7074,7 @@ void gen6_enable_rps(struct drm_i915_private *dev_priv) /* enable all PM interrupts */ I915_WRITE(GEN6_PMINTRMSK, 0); - __gen6_gt_force_wake_put(dev_priv); + gen6_gt_force_wake_put(dev_priv); } void intel_enable_clock_gating(struct drm_device *dev) -- cgit v1.1 From d1ebd816e6d7967c764f0cfa7d718f7c5cc7a8e4 Mon Sep 17 00:00:00 2001 From: Ben Widawsky Date: Mon, 25 Apr 2011 20:11:50 +0100 Subject: drm/i915: forcewake struct mutex locking fixes Found by the new strict checking for the mutex being held whilst manipulating the forcewake status. Signed-off-by: Ben Widawsky Signed-off-by: Chris Wilson Signed-off-by: Keith Packard --- drivers/gpu/drm/i915/intel_display.c | 9 +++++++++ 1 file changed, 9 insertions(+) (limited to 'drivers/gpu/drm/i915/intel_display.c') diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c index 220c3e0..5504ff2 100644 --- a/drivers/gpu/drm/i915/intel_display.c +++ b/drivers/gpu/drm/i915/intel_display.c @@ -2585,7 +2585,11 @@ static void ironlake_crtc_enable(struct drm_crtc *crtc) ironlake_pch_enable(crtc); intel_crtc_load_lut(crtc); + + mutex_lock(&dev->struct_mutex); intel_update_fbc(dev); + mutex_unlock(&dev->struct_mutex); + intel_crtc_update_cursor(crtc, true); } @@ -2681,8 +2685,11 @@ static void ironlake_crtc_disable(struct drm_crtc *crtc) intel_crtc->active = false; intel_update_watermarks(dev); + + mutex_lock(&dev->struct_mutex); intel_update_fbc(dev); intel_clear_scanline_wait(dev); + mutex_unlock(&dev->struct_mutex); } static void ironlake_crtc_dpms(struct drm_crtc *crtc, int mode) @@ -6973,6 +6980,7 @@ void gen6_enable_rps(struct drm_i915_private *dev_priv) * userspace... */ I915_WRITE(GEN6_RC_STATE, 0); + mutex_lock(&dev_priv->dev->struct_mutex); gen6_gt_force_wake_get(dev_priv); /* disable the counters and set deterministic thresholds */ @@ -7075,6 +7083,7 @@ void gen6_enable_rps(struct drm_i915_private *dev_priv) I915_WRITE(GEN6_PMINTRMSK, 0); gen6_gt_force_wake_put(dev_priv); + mutex_unlock(&dev_priv->dev->struct_mutex); } void intel_enable_clock_gating(struct drm_device *dev) -- cgit v1.1 From 4912d04193733a825216b926ffd290fada88ab07 Mon Sep 17 00:00:00 2001 From: Ben Widawsky Date: Mon, 25 Apr 2011 11:25:20 -0700 Subject: drm/i915: move gen6 rps handling to workqueue The render P-state handling code requires reading from a GT register. This means that FORCEWAKE must be written to, a resource which is shared and should be protected by struct_mutex. Hence we can not manipulate that register from within the interrupt handling and so must delegate the task to a workqueue. Signed-off-by: Ben Widawsky Signed-off-by: Chris Wilson Signed-off-by: Keith Packard --- drivers/gpu/drm/i915/intel_display.c | 8 ++++++++ 1 file changed, 8 insertions(+) (limited to 'drivers/gpu/drm/i915/intel_display.c') diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c index 5504ff2..784e52c 100644 --- a/drivers/gpu/drm/i915/intel_display.c +++ b/drivers/gpu/drm/i915/intel_display.c @@ -6876,6 +6876,11 @@ void gen6_disable_rps(struct drm_device *dev) I915_WRITE(GEN6_RPNSWREQ, 1 << 31); I915_WRITE(GEN6_PMINTRMSK, 0xffffffff); I915_WRITE(GEN6_PMIER, 0); + + spin_lock_irq(&dev_priv->rps_lock); + dev_priv->pm_iir = 0; + spin_unlock_irq(&dev_priv->rps_lock); + I915_WRITE(GEN6_PMIIR, I915_READ(GEN6_PMIIR)); } @@ -7078,7 +7083,10 @@ void gen6_enable_rps(struct drm_i915_private *dev_priv) GEN6_PM_RP_DOWN_THRESHOLD | GEN6_PM_RP_UP_EI_EXPIRED | GEN6_PM_RP_DOWN_EI_EXPIRED); + spin_lock_irq(&dev_priv->rps_lock); + WARN_ON(dev_priv->pm_iir != 0); I915_WRITE(GEN6_PMIMR, 0); + spin_unlock_irq(&dev_priv->rps_lock); /* enable all PM interrupts */ I915_WRITE(GEN6_PMINTRMSK, 0); -- cgit v1.1 From 674cf967614f31826f45d30c8f8f8e050cc3eef2 Mon Sep 17 00:00:00 2001 From: Jesse Barnes Date: Thu, 28 Apr 2011 14:27:04 -0700 Subject: drm/i915: make FDI training a display function Rather than branching in ironlake_pch_enable, add a new train_fdi function to the display function pointer struct and use it instead. Signed-off-by: Jesse Barnes Reviewed-by: Keith Packard Signed-off-by: Keith Packard --- drivers/gpu/drm/i915/intel_display.c | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) (limited to 'drivers/gpu/drm/i915/intel_display.c') diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c index 784e52c..ba618d5 100644 --- a/drivers/gpu/drm/i915/intel_display.c +++ b/drivers/gpu/drm/i915/intel_display.c @@ -2469,10 +2469,7 @@ static void ironlake_pch_enable(struct drm_crtc *crtc) u32 reg, temp; /* For PCH output, training FDI link */ - if (IS_GEN6(dev)) - gen6_fdi_link_train(crtc); - else - ironlake_fdi_link_train(crtc); + dev_priv->display.fdi_link_train(crtc); intel_enable_pch_pll(dev_priv, pipe); @@ -7431,6 +7428,7 @@ static void intel_init_display(struct drm_device *dev) "Disable CxSR\n"); dev_priv->display.update_wm = NULL; } + dev_priv->display.fdi_link_train = ironlake_fdi_link_train; } else if (IS_GEN6(dev)) { if (SNB_READ_WM0_LATENCY()) { dev_priv->display.update_wm = sandybridge_update_wm; @@ -7439,6 +7437,7 @@ static void intel_init_display(struct drm_device *dev) "Disable CxSR\n"); dev_priv->display.update_wm = NULL; } + dev_priv->display.fdi_link_train = gen6_fdi_link_train; } else dev_priv->display.update_wm = NULL; } else if (IS_PINEVIEW(dev)) { -- cgit v1.1 From 357555c00f8414057f0c12ee3f479f197264123d Mon Sep 17 00:00:00 2001 From: Jesse Barnes Date: Thu, 28 Apr 2011 15:09:55 -0700 Subject: drm/i915: manual FDI training for Ivy Bridge A0 stepping chips need to use manual training, but the bits have all moved. So fix things up so we can at least train FDI for VGA links. Signed-off-by: Jesse Barnes Reviewed-by: Keith Packard Signed-off-by: Keith Packard --- drivers/gpu/drm/i915/intel_display.c | 130 +++++++++++++++++++++++++++++++++-- 1 file changed, 126 insertions(+), 4 deletions(-) (limited to 'drivers/gpu/drm/i915/intel_display.c') diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c index ba618d5..5ccd18f 100644 --- a/drivers/gpu/drm/i915/intel_display.c +++ b/drivers/gpu/drm/i915/intel_display.c @@ -2051,8 +2051,13 @@ static void intel_fdi_normal_train(struct drm_crtc *crtc) /* enable normal train */ reg = FDI_TX_CTL(pipe); temp = I915_READ(reg); - temp &= ~FDI_LINK_TRAIN_NONE; - temp |= FDI_LINK_TRAIN_NONE | FDI_TX_ENHANCE_FRAME_ENABLE; + if (IS_GEN6(dev)) { + temp &= ~FDI_LINK_TRAIN_NONE; + temp |= FDI_LINK_TRAIN_NONE | FDI_TX_ENHANCE_FRAME_ENABLE; + } else if (IS_IVYBRIDGE(dev)) { + temp &= ~FDI_LINK_TRAIN_NONE_IVB; + temp |= FDI_LINK_TRAIN_NONE_IVB | FDI_TX_ENHANCE_FRAME_ENABLE; + } I915_WRITE(reg, temp); reg = FDI_RX_CTL(pipe); @@ -2069,6 +2074,11 @@ static void intel_fdi_normal_train(struct drm_crtc *crtc) /* wait one idle pattern time */ POSTING_READ(reg); udelay(1000); + + /* IVB wants error correction enabled */ + if (IS_IVYBRIDGE(dev)) + I915_WRITE(reg, I915_READ(reg) | FDI_FS_ERRC_ENABLE | + FDI_FE_ERRC_ENABLE); } /* The FDI link training functions for ILK/Ibexpeak. */ @@ -2296,7 +2306,116 @@ static void gen6_fdi_link_train(struct drm_crtc *crtc) DRM_DEBUG_KMS("FDI train done.\n"); } -static void ironlake_fdi_enable(struct drm_crtc *crtc) +/* Manual link training for Ivy Bridge A0 parts */ +static void ivb_manual_fdi_link_train(struct drm_crtc *crtc) +{ + struct drm_device *dev = crtc->dev; + struct drm_i915_private *dev_priv = dev->dev_private; + struct intel_crtc *intel_crtc = to_intel_crtc(crtc); + int pipe = intel_crtc->pipe; + u32 reg, temp, i; + + /* Train 1: umask FDI RX Interrupt symbol_lock and bit_lock bit + for train result */ + reg = FDI_RX_IMR(pipe); + temp = I915_READ(reg); + temp &= ~FDI_RX_SYMBOL_LOCK; + temp &= ~FDI_RX_BIT_LOCK; + I915_WRITE(reg, temp); + + POSTING_READ(reg); + udelay(150); + + /* enable CPU FDI TX and PCH FDI RX */ + reg = FDI_TX_CTL(pipe); + temp = I915_READ(reg); + temp &= ~(7 << 19); + temp |= (intel_crtc->fdi_lanes - 1) << 19; + temp &= ~(FDI_LINK_TRAIN_AUTO | FDI_LINK_TRAIN_NONE_IVB); + temp |= FDI_LINK_TRAIN_PATTERN_1_IVB; + temp &= ~FDI_LINK_TRAIN_VOL_EMP_MASK; + temp |= FDI_LINK_TRAIN_400MV_0DB_SNB_B; + I915_WRITE(reg, temp | FDI_TX_ENABLE); + + reg = FDI_RX_CTL(pipe); + temp = I915_READ(reg); + temp &= ~FDI_LINK_TRAIN_AUTO; + temp &= ~FDI_LINK_TRAIN_PATTERN_MASK_CPT; + temp |= FDI_LINK_TRAIN_PATTERN_1_CPT; + I915_WRITE(reg, temp | FDI_RX_ENABLE); + + POSTING_READ(reg); + udelay(150); + + for (i = 0; i < 4; i++ ) { + reg = FDI_TX_CTL(pipe); + temp = I915_READ(reg); + temp &= ~FDI_LINK_TRAIN_VOL_EMP_MASK; + temp |= snb_b_fdi_train_param[i]; + I915_WRITE(reg, temp); + + POSTING_READ(reg); + udelay(500); + + reg = FDI_RX_IIR(pipe); + temp = I915_READ(reg); + DRM_DEBUG_KMS("FDI_RX_IIR 0x%x\n", temp); + + if (temp & FDI_RX_BIT_LOCK || + (I915_READ(reg) & FDI_RX_BIT_LOCK)) { + I915_WRITE(reg, temp | FDI_RX_BIT_LOCK); + DRM_DEBUG_KMS("FDI train 1 done.\n"); + break; + } + } + if (i == 4) + DRM_ERROR("FDI train 1 fail!\n"); + + /* Train 2 */ + reg = FDI_TX_CTL(pipe); + temp = I915_READ(reg); + temp &= ~FDI_LINK_TRAIN_NONE_IVB; + temp |= FDI_LINK_TRAIN_PATTERN_2_IVB; + temp &= ~FDI_LINK_TRAIN_VOL_EMP_MASK; + temp |= FDI_LINK_TRAIN_400MV_0DB_SNB_B; + I915_WRITE(reg, temp); + + reg = FDI_RX_CTL(pipe); + temp = I915_READ(reg); + temp &= ~FDI_LINK_TRAIN_PATTERN_MASK_CPT; + temp |= FDI_LINK_TRAIN_PATTERN_2_CPT; + I915_WRITE(reg, temp); + + POSTING_READ(reg); + udelay(150); + + for (i = 0; i < 4; i++ ) { + reg = FDI_TX_CTL(pipe); + temp = I915_READ(reg); + temp &= ~FDI_LINK_TRAIN_VOL_EMP_MASK; + temp |= snb_b_fdi_train_param[i]; + I915_WRITE(reg, temp); + + POSTING_READ(reg); + udelay(500); + + reg = FDI_RX_IIR(pipe); + temp = I915_READ(reg); + DRM_DEBUG_KMS("FDI_RX_IIR 0x%x\n", temp); + + if (temp & FDI_RX_SYMBOL_LOCK) { + I915_WRITE(reg, temp | FDI_RX_SYMBOL_LOCK); + DRM_DEBUG_KMS("FDI train 2 done.\n"); + break; + } + } + if (i == 4) + DRM_ERROR("FDI train 2 fail!\n"); + + DRM_DEBUG_KMS("FDI train done.\n"); +} + +static void ironlake_fdi_pll_enable(struct drm_crtc *crtc) { struct drm_device *dev = crtc->dev; struct drm_i915_private *dev_priv = dev->dev_private; @@ -2559,7 +2678,7 @@ static void ironlake_crtc_enable(struct drm_crtc *crtc) is_pch_port = intel_crtc_driving_pch(crtc); if (is_pch_port) - ironlake_fdi_enable(crtc); + ironlake_fdi_pll_enable(crtc); else ironlake_fdi_disable(crtc); @@ -7438,6 +7557,9 @@ static void intel_init_display(struct drm_device *dev) dev_priv->display.update_wm = NULL; } dev_priv->display.fdi_link_train = gen6_fdi_link_train; + } else if (IS_IVYBRIDGE(dev)) { + /* FIXME: detect B0+ stepping and use auto training */ + dev_priv->display.fdi_link_train = ivb_manual_fdi_link_train; } else dev_priv->display.update_wm = NULL; } else if (IS_PINEVIEW(dev)) { -- cgit v1.1 From fe100d4da1ba8e0be9f38979da1817145e68f866 Mon Sep 17 00:00:00 2001 From: Jesse Barnes Date: Thu, 28 Apr 2011 14:29:45 -0700 Subject: drm/i915: treat Ivy Bridge watermarks like Sandy Bridge Not fully tested. Signed-off-by: Jesse Barnes Reviewed-by: Keith Packard Signed-off-by: Keith Packard --- drivers/gpu/drm/i915/intel_display.c | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) (limited to 'drivers/gpu/drm/i915/intel_display.c') diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c index 5ccd18f..b1de6cb 100644 --- a/drivers/gpu/drm/i915/intel_display.c +++ b/drivers/gpu/drm/i915/intel_display.c @@ -7298,7 +7298,7 @@ void intel_enable_clock_gating(struct drm_device *dev) _3D_CHICKEN2_WM_READ_PIPELINED); } - if (IS_GEN6(dev)) { + if (IS_GEN6(dev) || IS_IVYBRIDGE(dev)) { I915_WRITE(WM3_LP_ILK, 0); I915_WRITE(WM2_LP_ILK, 0); I915_WRITE(WM1_LP_ILK, 0); @@ -7560,6 +7560,13 @@ static void intel_init_display(struct drm_device *dev) } else if (IS_IVYBRIDGE(dev)) { /* FIXME: detect B0+ stepping and use auto training */ dev_priv->display.fdi_link_train = ivb_manual_fdi_link_train; + if (SNB_READ_WM0_LATENCY()) { + dev_priv->display.update_wm = sandybridge_update_wm; + } else { + DRM_DEBUG_KMS("Failed to read display plane latency. " + "Disable CxSR\n"); + dev_priv->display.update_wm = NULL; + } } else dev_priv->display.update_wm = NULL; } else if (IS_PINEVIEW(dev)) { -- cgit v1.1 From 51d56126a25280c2dfca6bd7f68a4e8183b679b1 Mon Sep 17 00:00:00 2001 From: Jesse Barnes Date: Wed, 6 Apr 2011 12:28:05 -0700 Subject: drm/i915: page flip support for Ivy Bridge Treat Ivy Bridge like previous chips as far as flip submission is concerned. Signed-off-by: Jesse Barnes Reviewed-by: Keith Packard Signed-off-by: Keith Packard --- drivers/gpu/drm/i915/intel_display.c | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers/gpu/drm/i915/intel_display.c') diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c index b1de6cb..18888a2 100644 --- a/drivers/gpu/drm/i915/intel_display.c +++ b/drivers/gpu/drm/i915/intel_display.c @@ -6431,6 +6431,7 @@ static int intel_crtc_page_flip(struct drm_crtc *crtc, break; case 6: + case 7: OUT_RING(MI_DISPLAY_FLIP | MI_DISPLAY_FLIP_PLANE(intel_crtc->plane)); OUT_RING(fb->pitch | obj->tiling_mode); -- cgit v1.1 From 6067aaeadb5b3df26f27ac827256b1ef01e674f5 Mon Sep 17 00:00:00 2001 From: Jesse Barnes Date: Thu, 28 Apr 2011 15:04:31 -0700 Subject: drm/i915: split clock gating init into per-chipset functions This helps contain the mess to init_display() instead. Signed-off-by: Jesse Barnes Reviewed-by: Keith Packard Signed-off-by: Keith Packard --- drivers/gpu/drm/i915/intel_display.c | 337 ++++++++++++++++++++--------------- 1 file changed, 193 insertions(+), 144 deletions(-) (limited to 'drivers/gpu/drm/i915/intel_display.c') diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c index 18888a2..7eeffaf 100644 --- a/drivers/gpu/drm/i915/intel_display.c +++ b/drivers/gpu/drm/i915/intel_display.c @@ -7211,161 +7211,194 @@ void gen6_enable_rps(struct drm_i915_private *dev_priv) mutex_unlock(&dev_priv->dev->struct_mutex); } -void intel_enable_clock_gating(struct drm_device *dev) +static void ironlake_init_clock_gating(struct drm_device *dev) +{ + struct drm_i915_private *dev_priv = dev->dev_private; + uint32_t dspclk_gate = VRHUNIT_CLOCK_GATE_DISABLE; + + /* Required for FBC */ + dspclk_gate |= DPFCUNIT_CLOCK_GATE_DISABLE | + DPFCRUNIT_CLOCK_GATE_DISABLE | + DPFDUNIT_CLOCK_GATE_DISABLE; + /* Required for CxSR */ + dspclk_gate |= DPARBUNIT_CLOCK_GATE_DISABLE; + + I915_WRITE(PCH_3DCGDIS0, + MARIUNIT_CLOCK_GATE_DISABLE | + SVSMUNIT_CLOCK_GATE_DISABLE); + I915_WRITE(PCH_3DCGDIS1, + VFMUNIT_CLOCK_GATE_DISABLE); + + I915_WRITE(PCH_DSPCLK_GATE_D, dspclk_gate); + + /* + * On Ibex Peak and Cougar Point, we need to disable clock + * gating for the panel power sequencer or it will fail to + * start up when no ports are active. + */ + I915_WRITE(SOUTH_DSPCLK_GATE_D, PCH_DPLSUNIT_CLOCK_GATE_DISABLE); + + /* + * According to the spec the following bits should be set in + * order to enable memory self-refresh + * The bit 22/21 of 0x42004 + * The bit 5 of 0x42020 + * The bit 15 of 0x45000 + */ + I915_WRITE(ILK_DISPLAY_CHICKEN2, + (I915_READ(ILK_DISPLAY_CHICKEN2) | + ILK_DPARB_GATE | ILK_VSDPFD_FULL)); + I915_WRITE(ILK_DSPCLK_GATE, + (I915_READ(ILK_DSPCLK_GATE) | + ILK_DPARB_CLK_GATE)); + I915_WRITE(DISP_ARB_CTL, + (I915_READ(DISP_ARB_CTL) | + DISP_FBC_WM_DIS)); + I915_WRITE(WM3_LP_ILK, 0); + I915_WRITE(WM2_LP_ILK, 0); + I915_WRITE(WM1_LP_ILK, 0); + + /* + * Based on the document from hardware guys the following bits + * should be set unconditionally in order to enable FBC. + * The bit 22 of 0x42000 + * The bit 22 of 0x42004 + * The bit 7,8,9 of 0x42020. + */ + if (IS_IRONLAKE_M(dev)) { + I915_WRITE(ILK_DISPLAY_CHICKEN1, + I915_READ(ILK_DISPLAY_CHICKEN1) | + ILK_FBCQ_DIS); + I915_WRITE(ILK_DISPLAY_CHICKEN2, + I915_READ(ILK_DISPLAY_CHICKEN2) | + ILK_DPARB_GATE); + I915_WRITE(ILK_DSPCLK_GATE, + I915_READ(ILK_DSPCLK_GATE) | + ILK_DPFC_DIS1 | + ILK_DPFC_DIS2 | + ILK_CLK_FBC); + } + + I915_WRITE(ILK_DISPLAY_CHICKEN2, + I915_READ(ILK_DISPLAY_CHICKEN2) | + ILK_ELPIN_409_SELECT); + I915_WRITE(_3D_CHICKEN2, + _3D_CHICKEN2_WM_READ_PIPELINED << 16 | + _3D_CHICKEN2_WM_READ_PIPELINED); +} + +static void gen6_init_clock_gating(struct drm_device *dev) { struct drm_i915_private *dev_priv = dev->dev_private; int pipe; + uint32_t dspclk_gate = VRHUNIT_CLOCK_GATE_DISABLE; + + I915_WRITE(PCH_DSPCLK_GATE_D, dspclk_gate); /* - * Disable clock gating reported to work incorrectly according to the - * specs, but enable as much else as we can. + * On Ibex Peak and Cougar Point, we need to disable clock + * gating for the panel power sequencer or it will fail to + * start up when no ports are active. */ - if (HAS_PCH_SPLIT(dev)) { - uint32_t dspclk_gate = VRHUNIT_CLOCK_GATE_DISABLE; + I915_WRITE(SOUTH_DSPCLK_GATE_D, PCH_DPLSUNIT_CLOCK_GATE_DISABLE); - if (IS_GEN5(dev)) { - /* Required for FBC */ - dspclk_gate |= DPFCUNIT_CLOCK_GATE_DISABLE | - DPFCRUNIT_CLOCK_GATE_DISABLE | - DPFDUNIT_CLOCK_GATE_DISABLE; - /* Required for CxSR */ - dspclk_gate |= DPARBUNIT_CLOCK_GATE_DISABLE; - - I915_WRITE(PCH_3DCGDIS0, - MARIUNIT_CLOCK_GATE_DISABLE | - SVSMUNIT_CLOCK_GATE_DISABLE); - I915_WRITE(PCH_3DCGDIS1, - VFMUNIT_CLOCK_GATE_DISABLE); - } + I915_WRITE(ILK_DISPLAY_CHICKEN2, + I915_READ(ILK_DISPLAY_CHICKEN2) | + ILK_ELPIN_409_SELECT); - I915_WRITE(PCH_DSPCLK_GATE_D, dspclk_gate); + I915_WRITE(WM3_LP_ILK, 0); + I915_WRITE(WM2_LP_ILK, 0); + I915_WRITE(WM1_LP_ILK, 0); - /* - * On Ibex Peak and Cougar Point, we need to disable clock - * gating for the panel power sequencer or it will fail to - * start up when no ports are active. - */ - I915_WRITE(SOUTH_DSPCLK_GATE_D, PCH_DPLSUNIT_CLOCK_GATE_DISABLE); + /* + * According to the spec the following bits should be + * set in order to enable memory self-refresh and fbc: + * The bit21 and bit22 of 0x42000 + * The bit21 and bit22 of 0x42004 + * The bit5 and bit7 of 0x42020 + * The bit14 of 0x70180 + * The bit14 of 0x71180 + */ + I915_WRITE(ILK_DISPLAY_CHICKEN1, + I915_READ(ILK_DISPLAY_CHICKEN1) | + ILK_FBCQ_DIS | ILK_PABSTRETCH_DIS); + I915_WRITE(ILK_DISPLAY_CHICKEN2, + I915_READ(ILK_DISPLAY_CHICKEN2) | + ILK_DPARB_GATE | ILK_VSDPFD_FULL); + I915_WRITE(ILK_DSPCLK_GATE, + I915_READ(ILK_DSPCLK_GATE) | + ILK_DPARB_CLK_GATE | + ILK_DPFD_CLK_GATE); - /* - * According to the spec the following bits should be set in - * order to enable memory self-refresh - * The bit 22/21 of 0x42004 - * The bit 5 of 0x42020 - * The bit 15 of 0x45000 - */ - if (IS_GEN5(dev)) { - I915_WRITE(ILK_DISPLAY_CHICKEN2, - (I915_READ(ILK_DISPLAY_CHICKEN2) | - ILK_DPARB_GATE | ILK_VSDPFD_FULL)); - I915_WRITE(ILK_DSPCLK_GATE, - (I915_READ(ILK_DSPCLK_GATE) | - ILK_DPARB_CLK_GATE)); - I915_WRITE(DISP_ARB_CTL, - (I915_READ(DISP_ARB_CTL) | - DISP_FBC_WM_DIS)); - I915_WRITE(WM3_LP_ILK, 0); - I915_WRITE(WM2_LP_ILK, 0); - I915_WRITE(WM1_LP_ILK, 0); - } - /* - * Based on the document from hardware guys the following bits - * should be set unconditionally in order to enable FBC. - * The bit 22 of 0x42000 - * The bit 22 of 0x42004 - * The bit 7,8,9 of 0x42020. - */ - if (IS_IRONLAKE_M(dev)) { - I915_WRITE(ILK_DISPLAY_CHICKEN1, - I915_READ(ILK_DISPLAY_CHICKEN1) | - ILK_FBCQ_DIS); - I915_WRITE(ILK_DISPLAY_CHICKEN2, - I915_READ(ILK_DISPLAY_CHICKEN2) | - ILK_DPARB_GATE); - I915_WRITE(ILK_DSPCLK_GATE, - I915_READ(ILK_DSPCLK_GATE) | - ILK_DPFC_DIS1 | - ILK_DPFC_DIS2 | - ILK_CLK_FBC); - } + for_each_pipe(pipe) + I915_WRITE(DSPCNTR(pipe), + I915_READ(DSPCNTR(pipe)) | + DISPPLANE_TRICKLE_FEED_DISABLE); +} - I915_WRITE(ILK_DISPLAY_CHICKEN2, - I915_READ(ILK_DISPLAY_CHICKEN2) | - ILK_ELPIN_409_SELECT); +static void g4x_init_clock_gating(struct drm_device *dev) +{ + struct drm_i915_private *dev_priv = dev->dev_private; + uint32_t dspclk_gate; - if (IS_GEN5(dev)) { - I915_WRITE(_3D_CHICKEN2, - _3D_CHICKEN2_WM_READ_PIPELINED << 16 | - _3D_CHICKEN2_WM_READ_PIPELINED); - } + I915_WRITE(RENCLK_GATE_D1, 0); + I915_WRITE(RENCLK_GATE_D2, VF_UNIT_CLOCK_GATE_DISABLE | + GS_UNIT_CLOCK_GATE_DISABLE | + CL_UNIT_CLOCK_GATE_DISABLE); + I915_WRITE(RAMCLK_GATE_D, 0); + dspclk_gate = VRHUNIT_CLOCK_GATE_DISABLE | + OVRUNIT_CLOCK_GATE_DISABLE | + OVCUNIT_CLOCK_GATE_DISABLE; + if (IS_GM45(dev)) + dspclk_gate |= DSSUNIT_CLOCK_GATE_DISABLE; + I915_WRITE(DSPCLK_GATE_D, dspclk_gate); +} - if (IS_GEN6(dev) || IS_IVYBRIDGE(dev)) { - I915_WRITE(WM3_LP_ILK, 0); - I915_WRITE(WM2_LP_ILK, 0); - I915_WRITE(WM1_LP_ILK, 0); +static void crestline_init_clock_gating(struct drm_device *dev) +{ + struct drm_i915_private *dev_priv = dev->dev_private; - /* - * According to the spec the following bits should be - * set in order to enable memory self-refresh and fbc: - * The bit21 and bit22 of 0x42000 - * The bit21 and bit22 of 0x42004 - * The bit5 and bit7 of 0x42020 - * The bit14 of 0x70180 - * The bit14 of 0x71180 - */ - I915_WRITE(ILK_DISPLAY_CHICKEN1, - I915_READ(ILK_DISPLAY_CHICKEN1) | - ILK_FBCQ_DIS | ILK_PABSTRETCH_DIS); - I915_WRITE(ILK_DISPLAY_CHICKEN2, - I915_READ(ILK_DISPLAY_CHICKEN2) | - ILK_DPARB_GATE | ILK_VSDPFD_FULL); - I915_WRITE(ILK_DSPCLK_GATE, - I915_READ(ILK_DSPCLK_GATE) | - ILK_DPARB_CLK_GATE | - ILK_DPFD_CLK_GATE); - - for_each_pipe(pipe) - I915_WRITE(DSPCNTR(pipe), - I915_READ(DSPCNTR(pipe)) | - DISPPLANE_TRICKLE_FEED_DISABLE); - } - } else if (IS_G4X(dev)) { - uint32_t dspclk_gate; - I915_WRITE(RENCLK_GATE_D1, 0); - I915_WRITE(RENCLK_GATE_D2, VF_UNIT_CLOCK_GATE_DISABLE | - GS_UNIT_CLOCK_GATE_DISABLE | - CL_UNIT_CLOCK_GATE_DISABLE); - I915_WRITE(RAMCLK_GATE_D, 0); - dspclk_gate = VRHUNIT_CLOCK_GATE_DISABLE | - OVRUNIT_CLOCK_GATE_DISABLE | - OVCUNIT_CLOCK_GATE_DISABLE; - if (IS_GM45(dev)) - dspclk_gate |= DSSUNIT_CLOCK_GATE_DISABLE; - I915_WRITE(DSPCLK_GATE_D, dspclk_gate); - } else if (IS_CRESTLINE(dev)) { - I915_WRITE(RENCLK_GATE_D1, I965_RCC_CLOCK_GATE_DISABLE); - I915_WRITE(RENCLK_GATE_D2, 0); - I915_WRITE(DSPCLK_GATE_D, 0); - I915_WRITE(RAMCLK_GATE_D, 0); - I915_WRITE16(DEUC, 0); - } else if (IS_BROADWATER(dev)) { - I915_WRITE(RENCLK_GATE_D1, I965_RCZ_CLOCK_GATE_DISABLE | - I965_RCC_CLOCK_GATE_DISABLE | - I965_RCPB_CLOCK_GATE_DISABLE | - I965_ISC_CLOCK_GATE_DISABLE | - I965_FBC_CLOCK_GATE_DISABLE); - I915_WRITE(RENCLK_GATE_D2, 0); - } else if (IS_GEN3(dev)) { - u32 dstate = I915_READ(D_STATE); + I915_WRITE(RENCLK_GATE_D1, I965_RCC_CLOCK_GATE_DISABLE); + I915_WRITE(RENCLK_GATE_D2, 0); + I915_WRITE(DSPCLK_GATE_D, 0); + I915_WRITE(RAMCLK_GATE_D, 0); + I915_WRITE16(DEUC, 0); +} - dstate |= DSTATE_PLL_D3_OFF | DSTATE_GFX_CLOCK_GATING | - DSTATE_DOT_CLOCK_GATING; - I915_WRITE(D_STATE, dstate); - } else if (IS_I85X(dev) || IS_I865G(dev)) { - I915_WRITE(RENCLK_GATE_D1, SV_CLOCK_GATE_DISABLE); - } else if (IS_I830(dev)) { - I915_WRITE(DSPCLK_GATE_D, OVRUNIT_CLOCK_GATE_DISABLE); - } +static void broadwater_init_clock_gating(struct drm_device *dev) +{ + struct drm_i915_private *dev_priv = dev->dev_private; + + I915_WRITE(RENCLK_GATE_D1, I965_RCZ_CLOCK_GATE_DISABLE | + I965_RCC_CLOCK_GATE_DISABLE | + I965_RCPB_CLOCK_GATE_DISABLE | + I965_ISC_CLOCK_GATE_DISABLE | + I965_FBC_CLOCK_GATE_DISABLE); + I915_WRITE(RENCLK_GATE_D2, 0); +} + +static void gen3_init_clock_gating(struct drm_device *dev) +{ + struct drm_i915_private *dev_priv = dev->dev_private; + u32 dstate = I915_READ(D_STATE); + + dstate |= DSTATE_PLL_D3_OFF | DSTATE_GFX_CLOCK_GATING | + DSTATE_DOT_CLOCK_GATING; + I915_WRITE(D_STATE, dstate); +} + +static void i85x_init_clock_gating(struct drm_device *dev) +{ + struct drm_i915_private *dev_priv = dev->dev_private; + + I915_WRITE(RENCLK_GATE_D1, SV_CLOCK_GATE_DISABLE); +} + +static void i830_init_clock_gating(struct drm_device *dev) +{ + struct drm_i915_private *dev_priv = dev->dev_private; + + I915_WRITE(DSPCLK_GATE_D, OVRUNIT_CLOCK_GATE_DISABLE); } static void ironlake_teardown_rc6(struct drm_device *dev) @@ -7549,6 +7582,7 @@ static void intel_init_display(struct drm_device *dev) dev_priv->display.update_wm = NULL; } dev_priv->display.fdi_link_train = ironlake_fdi_link_train; + dev_priv->display.init_clock_gating = ironlake_init_clock_gating; } else if (IS_GEN6(dev)) { if (SNB_READ_WM0_LATENCY()) { dev_priv->display.update_wm = sandybridge_update_wm; @@ -7558,6 +7592,7 @@ static void intel_init_display(struct drm_device *dev) dev_priv->display.update_wm = NULL; } dev_priv->display.fdi_link_train = gen6_fdi_link_train; + dev_priv->display.init_clock_gating = gen6_init_clock_gating; } else if (IS_IVYBRIDGE(dev)) { /* FIXME: detect B0+ stepping and use auto training */ dev_priv->display.fdi_link_train = ivb_manual_fdi_link_train; @@ -7568,6 +7603,8 @@ static void intel_init_display(struct drm_device *dev) "Disable CxSR\n"); dev_priv->display.update_wm = NULL; } + dev_priv->display.init_clock_gating = gen6_init_clock_gating; + } else dev_priv->display.update_wm = NULL; } else if (IS_PINEVIEW(dev)) { @@ -7585,18 +7622,30 @@ static void intel_init_display(struct drm_device *dev) dev_priv->display.update_wm = NULL; } else dev_priv->display.update_wm = pineview_update_wm; - } else if (IS_G4X(dev)) + } else if (IS_G4X(dev)) { dev_priv->display.update_wm = g4x_update_wm; - else if (IS_GEN4(dev)) + dev_priv->display.init_clock_gating = g4x_init_clock_gating; + } else if (IS_GEN4(dev)) { dev_priv->display.update_wm = i965_update_wm; - else if (IS_GEN3(dev)) { + if (IS_CRESTLINE(dev)) + dev_priv->display.init_clock_gating = crestline_init_clock_gating; + else if (IS_BROADWATER(dev)) + dev_priv->display.init_clock_gating = broadwater_init_clock_gating; + } else if (IS_GEN3(dev)) { dev_priv->display.update_wm = i9xx_update_wm; dev_priv->display.get_fifo_size = i9xx_get_fifo_size; + dev_priv->display.init_clock_gating = gen3_init_clock_gating; + } else if (IS_I865G(dev)) { + dev_priv->display.update_wm = i830_update_wm; + dev_priv->display.init_clock_gating = i85x_init_clock_gating; + dev_priv->display.get_fifo_size = i830_get_fifo_size; } else if (IS_I85X(dev)) { dev_priv->display.update_wm = i9xx_update_wm; dev_priv->display.get_fifo_size = i85x_get_fifo_size; + dev_priv->display.init_clock_gating = i85x_init_clock_gating; } else { dev_priv->display.update_wm = i830_update_wm; + dev_priv->display.init_clock_gating = i830_init_clock_gating; if (IS_845G(dev)) dev_priv->display.get_fifo_size = i845_get_fifo_size; else @@ -7726,7 +7775,7 @@ void intel_modeset_init(struct drm_device *dev) i915_disable_vga(dev); intel_setup_outputs(dev); - intel_enable_clock_gating(dev); + dev_priv->display.init_clock_gating(dev); if (IS_IRONLAKE_M(dev)) { ironlake_enable_drps(dev); -- cgit v1.1 From 28963a3eb5e2ae861995c2f7c15c7de982b3ce0e Mon Sep 17 00:00:00 2001 From: Jesse Barnes Date: Wed, 11 May 2011 09:42:30 -0700 Subject: drm/i915: add Ivybridge clock gating init function Some of the bits have changed, including one we were setting that enables a VGA test mode, preventing pipe B from working at all. So add a new IVB specific function with the right bits. Signed-off-by: Jesse Barnes Reviewed-by: Keith Packard Signed-off-by: Keith Packard --- drivers/gpu/drm/i915/intel_display.c | 29 ++++++++++++++++++++++++++++- 1 file changed, 28 insertions(+), 1 deletion(-) (limited to 'drivers/gpu/drm/i915/intel_display.c') diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c index 7eeffaf..b8b4a2e 100644 --- a/drivers/gpu/drm/i915/intel_display.c +++ b/drivers/gpu/drm/i915/intel_display.c @@ -7336,6 +7336,33 @@ static void gen6_init_clock_gating(struct drm_device *dev) DISPPLANE_TRICKLE_FEED_DISABLE); } +static void ivybridge_init_clock_gating(struct drm_device *dev) +{ + struct drm_i915_private *dev_priv = dev->dev_private; + int pipe; + uint32_t dspclk_gate = VRHUNIT_CLOCK_GATE_DISABLE; + + I915_WRITE(PCH_DSPCLK_GATE_D, dspclk_gate); + + /* + * On Ibex Peak and Cougar Point, we need to disable clock + * gating for the panel power sequencer or it will fail to + * start up when no ports are active. + */ + I915_WRITE(SOUTH_DSPCLK_GATE_D, PCH_DPLSUNIT_CLOCK_GATE_DISABLE); + + I915_WRITE(WM3_LP_ILK, 0); + I915_WRITE(WM2_LP_ILK, 0); + I915_WRITE(WM1_LP_ILK, 0); + + I915_WRITE(ILK_DSPCLK_GATE, IVB_VRHUNIT_CLK_GATE); + + for_each_pipe(pipe) + I915_WRITE(DSPCNTR(pipe), + I915_READ(DSPCNTR(pipe)) | + DISPPLANE_TRICKLE_FEED_DISABLE); +} + static void g4x_init_clock_gating(struct drm_device *dev) { struct drm_i915_private *dev_priv = dev->dev_private; @@ -7603,7 +7630,7 @@ static void intel_init_display(struct drm_device *dev) "Disable CxSR\n"); dev_priv->display.update_wm = NULL; } - dev_priv->display.init_clock_gating = gen6_init_clock_gating; + dev_priv->display.init_clock_gating = ivybridge_init_clock_gating; } else dev_priv->display.update_wm = NULL; -- cgit v1.1 From 645c62a5e95a5f9a8e0d0627446bbda4ee042024 Mon Sep 17 00:00:00 2001 From: Jesse Barnes Date: Wed, 11 May 2011 09:49:31 -0700 Subject: drm/i915: split PCH clock gating init Ibex Peak and CougarPoint already require a different setting (added here), and future chips will likely follow that precedent. Signed-off-by: Jesse Barnes Reviewed-by: Keith Packard Signed-off-by: Keith Packard --- drivers/gpu/drm/i915/intel_display.c | 63 +++++++++++++++++++++++------------- 1 file changed, 41 insertions(+), 22 deletions(-) (limited to 'drivers/gpu/drm/i915/intel_display.c') diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c index b8b4a2e..5ec74df 100644 --- a/drivers/gpu/drm/i915/intel_display.c +++ b/drivers/gpu/drm/i915/intel_display.c @@ -7232,13 +7232,6 @@ static void ironlake_init_clock_gating(struct drm_device *dev) I915_WRITE(PCH_DSPCLK_GATE_D, dspclk_gate); /* - * On Ibex Peak and Cougar Point, we need to disable clock - * gating for the panel power sequencer or it will fail to - * start up when no ports are active. - */ - I915_WRITE(SOUTH_DSPCLK_GATE_D, PCH_DPLSUNIT_CLOCK_GATE_DISABLE); - - /* * According to the spec the following bits should be set in * order to enable memory self-refresh * The bit 22/21 of 0x42004 @@ -7295,13 +7288,6 @@ static void gen6_init_clock_gating(struct drm_device *dev) I915_WRITE(PCH_DSPCLK_GATE_D, dspclk_gate); - /* - * On Ibex Peak and Cougar Point, we need to disable clock - * gating for the panel power sequencer or it will fail to - * start up when no ports are active. - */ - I915_WRITE(SOUTH_DSPCLK_GATE_D, PCH_DPLSUNIT_CLOCK_GATE_DISABLE); - I915_WRITE(ILK_DISPLAY_CHICKEN2, I915_READ(ILK_DISPLAY_CHICKEN2) | ILK_ELPIN_409_SELECT); @@ -7344,13 +7330,6 @@ static void ivybridge_init_clock_gating(struct drm_device *dev) I915_WRITE(PCH_DSPCLK_GATE_D, dspclk_gate); - /* - * On Ibex Peak and Cougar Point, we need to disable clock - * gating for the panel power sequencer or it will fail to - * start up when no ports are active. - */ - I915_WRITE(SOUTH_DSPCLK_GATE_D, PCH_DPLSUNIT_CLOCK_GATE_DISABLE); - I915_WRITE(WM3_LP_ILK, 0); I915_WRITE(WM2_LP_ILK, 0); I915_WRITE(WM1_LP_ILK, 0); @@ -7428,6 +7407,32 @@ static void i830_init_clock_gating(struct drm_device *dev) I915_WRITE(DSPCLK_GATE_D, OVRUNIT_CLOCK_GATE_DISABLE); } +static void ibx_init_clock_gating(struct drm_device *dev) +{ + struct drm_i915_private *dev_priv = dev->dev_private; + + /* + * On Ibex Peak and Cougar Point, we need to disable clock + * gating for the panel power sequencer or it will fail to + * start up when no ports are active. + */ + I915_WRITE(SOUTH_DSPCLK_GATE_D, PCH_DPLSUNIT_CLOCK_GATE_DISABLE); +} + +static void cpt_init_clock_gating(struct drm_device *dev) +{ + struct drm_i915_private *dev_priv = dev->dev_private; + + /* + * On Ibex Peak and Cougar Point, we need to disable clock + * gating for the panel power sequencer or it will fail to + * start up when no ports are active. + */ + I915_WRITE(SOUTH_DSPCLK_GATE_D, PCH_DPLSUNIT_CLOCK_GATE_DISABLE); + I915_WRITE(SOUTH_CHICKEN2, I915_READ(SOUTH_CHICKEN2) | + DPLS_EDP_PPS_FIX_DIS); +} + static void ironlake_teardown_rc6(struct drm_device *dev) { struct drm_i915_private *dev_priv = dev->dev_private; @@ -7543,6 +7548,15 @@ void ironlake_enable_rc6(struct drm_device *dev) mutex_unlock(&dev->struct_mutex); } +void intel_init_clock_gating(struct drm_device *dev) +{ + struct drm_i915_private *dev_priv = dev->dev_private; + + dev_priv->display.init_clock_gating(dev); + + if (dev_priv->display.init_pch_clock_gating) + dev_priv->display.init_pch_clock_gating(dev); +} /* Set up chip specific display functions */ static void intel_init_display(struct drm_device *dev) @@ -7600,6 +7614,11 @@ static void intel_init_display(struct drm_device *dev) /* For FIFO watermark updates */ if (HAS_PCH_SPLIT(dev)) { + if (HAS_PCH_IBX(dev)) + dev_priv->display.init_pch_clock_gating = ibx_init_clock_gating; + else if (HAS_PCH_CPT(dev)) + dev_priv->display.init_pch_clock_gating = cpt_init_clock_gating; + if (IS_GEN5(dev)) { if (I915_READ(MLTR_ILK) & ILK_SRLT_MASK) dev_priv->display.update_wm = ironlake_update_wm; @@ -7802,7 +7821,7 @@ void intel_modeset_init(struct drm_device *dev) i915_disable_vga(dev); intel_setup_outputs(dev); - dev_priv->display.init_clock_gating(dev); + intel_init_clock_gating(dev); if (IS_IRONLAKE_M(dev)) { ironlake_enable_drps(dev); -- cgit v1.1 From c1a9f047638b27e481d097910604316b8a0d132b Mon Sep 17 00:00:00 2001 From: Jesse Barnes Date: Thu, 5 May 2011 15:24:21 -0700 Subject: drm/i915: add fbc enable flag, but disable by default FBC has too many corner cases that we don't currently deal with, so disable it by default so we can enable more important features like RC6, which conflicts in some configurations. Bugzilla: https://bugs.freedesktop.org/show_bug.cgi?id=31742 Signed-off-by: Jesse Barnes Reviewed-by: Ben Widawsky Signed-off-by: Keith Packard --- drivers/gpu/drm/i915/intel_display.c | 5 +++++ 1 file changed, 5 insertions(+) (limited to 'drivers/gpu/drm/i915/intel_display.c') diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c index 5ec74df..81ad654 100644 --- a/drivers/gpu/drm/i915/intel_display.c +++ b/drivers/gpu/drm/i915/intel_display.c @@ -1731,6 +1731,11 @@ static void intel_update_fbc(struct drm_device *dev) intel_fb = to_intel_framebuffer(fb); obj = intel_fb->obj; + if (!i915_enable_fbc) { + DRM_DEBUG_KMS("fbc disabled per module param (default off)\n"); + dev_priv->no_fbc_reason = FBC_MODULE_PARAM; + goto out_disable; + } if (intel_fb->obj->base.size > dev_priv->cfb_size) { DRM_DEBUG_KMS("framebuffer too large, disabling " "compression\n"); -- cgit v1.1 From 61e499bf05254aca0fab08e2c91643331a15e725 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Tue, 17 May 2011 16:13:52 -0700 Subject: drm/i915: FDI link training broken on Ironlake by Ivybridge integration Commit 357555c00f8414057f0c12ee3f479f197264123d split out IVB-specific register definitions for FDI link training, but a piece of that commit stopped executing some critical code on Ironlake systems while leaving it running on Sandybridge. Turn that code back on both Ironlake and Sandybridge Signed-off-by: Keith Packard Acked-by: Jesse Barnes --- drivers/gpu/drm/i915/intel_display.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'drivers/gpu/drm/i915/intel_display.c') diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c index 81ad654..455d885 100644 --- a/drivers/gpu/drm/i915/intel_display.c +++ b/drivers/gpu/drm/i915/intel_display.c @@ -2056,12 +2056,12 @@ static void intel_fdi_normal_train(struct drm_crtc *crtc) /* enable normal train */ reg = FDI_TX_CTL(pipe); temp = I915_READ(reg); - if (IS_GEN6(dev)) { - temp &= ~FDI_LINK_TRAIN_NONE; - temp |= FDI_LINK_TRAIN_NONE | FDI_TX_ENHANCE_FRAME_ENABLE; - } else if (IS_IVYBRIDGE(dev)) { + if (IS_IVYBRIDGE(dev)) { temp &= ~FDI_LINK_TRAIN_NONE_IVB; temp |= FDI_LINK_TRAIN_NONE_IVB | FDI_TX_ENHANCE_FRAME_ENABLE; + } else { + temp &= ~FDI_LINK_TRAIN_NONE; + temp |= FDI_LINK_TRAIN_NONE | FDI_TX_ENHANCE_FRAME_ENABLE; } I915_WRITE(reg, temp); -- cgit v1.1