Commit e516c7df authored by Dave Airlie's avatar Dave Airlie

Merge branch 'drm-intel-fixes' of...

Merge branch 'drm-intel-fixes' of git://git.kernel.org/pub/scm/linux/kernel/git/ickle/drm-intel into drm-fixes
parents 81e8d216 1b39d6f3
...@@ -812,8 +812,10 @@ static int intel_fake_agp_fetch_size(void) ...@@ -812,8 +812,10 @@ static int intel_fake_agp_fetch_size(void)
static void i830_cleanup(void) static void i830_cleanup(void)
{ {
kunmap(intel_private.i8xx_page); if (intel_private.i8xx_flush_page) {
intel_private.i8xx_flush_page = NULL; kunmap(intel_private.i8xx_flush_page);
intel_private.i8xx_flush_page = NULL;
}
__free_page(intel_private.i8xx_page); __free_page(intel_private.i8xx_page);
intel_private.i8xx_page = NULL; intel_private.i8xx_page = NULL;
......
...@@ -767,6 +767,9 @@ static int i915_getparam(struct drm_device *dev, void *data, ...@@ -767,6 +767,9 @@ static int i915_getparam(struct drm_device *dev, void *data,
case I915_PARAM_HAS_BLT: case I915_PARAM_HAS_BLT:
value = HAS_BLT(dev); value = HAS_BLT(dev);
break; break;
case I915_PARAM_HAS_COHERENT_RINGS:
value = 1;
break;
default: default:
DRM_DEBUG_DRIVER("Unknown parameter %d\n", DRM_DEBUG_DRIVER("Unknown parameter %d\n",
param->param); param->param);
......
...@@ -4374,10 +4374,20 @@ i915_gem_busy_ioctl(struct drm_device *dev, void *data, ...@@ -4374,10 +4374,20 @@ i915_gem_busy_ioctl(struct drm_device *dev, void *data,
* use this buffer rather sooner than later, so issuing the required * use this buffer rather sooner than later, so issuing the required
* flush earlier is beneficial. * flush earlier is beneficial.
*/ */
if (obj->write_domain & I915_GEM_GPU_DOMAINS) if (obj->write_domain & I915_GEM_GPU_DOMAINS) {
i915_gem_flush_ring(dev, file_priv, i915_gem_flush_ring(dev, file_priv,
obj_priv->ring, obj_priv->ring,
0, obj->write_domain); 0, obj->write_domain);
} else if (obj_priv->ring->outstanding_lazy_request) {
/* This ring is not being cleared by active usage,
* so emit a request to do so.
*/
u32 seqno = i915_add_request(dev,
NULL, NULL,
obj_priv->ring);
if (seqno == 0)
ret = -ENOMEM;
}
/* Update the active list for the hardware's current position. /* Update the active list for the hardware's current position.
* Otherwise this only updates on a delayed timer or when irqs * Otherwise this only updates on a delayed timer or when irqs
......
...@@ -3033,6 +3033,7 @@ ...@@ -3033,6 +3033,7 @@
#define TRANS_DP_10BPC (1<<9) #define TRANS_DP_10BPC (1<<9)
#define TRANS_DP_6BPC (2<<9) #define TRANS_DP_6BPC (2<<9)
#define TRANS_DP_12BPC (3<<9) #define TRANS_DP_12BPC (3<<9)
#define TRANS_DP_BPC_MASK (3<<9)
#define TRANS_DP_VSYNC_ACTIVE_HIGH (1<<4) #define TRANS_DP_VSYNC_ACTIVE_HIGH (1<<4)
#define TRANS_DP_VSYNC_ACTIVE_LOW 0 #define TRANS_DP_VSYNC_ACTIVE_LOW 0
#define TRANS_DP_HSYNC_ACTIVE_HIGH (1<<3) #define TRANS_DP_HSYNC_ACTIVE_HIGH (1<<3)
......
...@@ -2120,9 +2120,11 @@ static void ironlake_crtc_enable(struct drm_crtc *crtc) ...@@ -2120,9 +2120,11 @@ static void ironlake_crtc_enable(struct drm_crtc *crtc)
reg = TRANS_DP_CTL(pipe); reg = TRANS_DP_CTL(pipe);
temp = I915_READ(reg); temp = I915_READ(reg);
temp &= ~(TRANS_DP_PORT_SEL_MASK | temp &= ~(TRANS_DP_PORT_SEL_MASK |
TRANS_DP_SYNC_MASK); TRANS_DP_SYNC_MASK |
TRANS_DP_BPC_MASK);
temp |= (TRANS_DP_OUTPUT_ENABLE | temp |= (TRANS_DP_OUTPUT_ENABLE |
TRANS_DP_ENH_FRAMING); TRANS_DP_ENH_FRAMING);
temp |= TRANS_DP_8BPC;
if (crtc->mode.flags & DRM_MODE_FLAG_PHSYNC) if (crtc->mode.flags & DRM_MODE_FLAG_PHSYNC)
temp |= TRANS_DP_HSYNC_ACTIVE_HIGH; temp |= TRANS_DP_HSYNC_ACTIVE_HIGH;
...@@ -2712,27 +2714,19 @@ fdi_reduce_ratio(u32 *num, u32 *den) ...@@ -2712,27 +2714,19 @@ fdi_reduce_ratio(u32 *num, u32 *den)
} }
} }
#define DATA_N 0x800000
#define LINK_N 0x80000
static void static void
ironlake_compute_m_n(int bits_per_pixel, int nlanes, int pixel_clock, ironlake_compute_m_n(int bits_per_pixel, int nlanes, int pixel_clock,
int link_clock, struct fdi_m_n *m_n) int link_clock, struct fdi_m_n *m_n)
{ {
u64 temp;
m_n->tu = 64; /* default size */ m_n->tu = 64; /* default size */
temp = (u64) DATA_N * pixel_clock; /* BUG_ON(pixel_clock > INT_MAX / 36); */
temp = div_u64(temp, link_clock); m_n->gmch_m = bits_per_pixel * pixel_clock;
m_n->gmch_m = div_u64(temp * bits_per_pixel, nlanes); m_n->gmch_n = link_clock * nlanes * 8;
m_n->gmch_m >>= 3; /* convert to bytes_per_pixel */
m_n->gmch_n = DATA_N;
fdi_reduce_ratio(&m_n->gmch_m, &m_n->gmch_n); fdi_reduce_ratio(&m_n->gmch_m, &m_n->gmch_n);
temp = (u64) LINK_N * pixel_clock; m_n->link_m = pixel_clock;
m_n->link_m = div_u64(temp, link_clock); m_n->link_n = link_clock;
m_n->link_n = LINK_N;
fdi_reduce_ratio(&m_n->link_m, &m_n->link_n); fdi_reduce_ratio(&m_n->link_m, &m_n->link_n);
} }
...@@ -3716,6 +3710,7 @@ static int intel_crtc_mode_set(struct drm_crtc *crtc, ...@@ -3716,6 +3710,7 @@ static int intel_crtc_mode_set(struct drm_crtc *crtc,
/* FDI link */ /* FDI link */
if (HAS_PCH_SPLIT(dev)) { if (HAS_PCH_SPLIT(dev)) {
int pixel_multiplier = intel_mode_get_pixel_multiplier(adjusted_mode);
int lane = 0, link_bw, bpp; int lane = 0, link_bw, bpp;
/* CPU eDP doesn't require FDI link, so just set DP M/N /* CPU eDP doesn't require FDI link, so just set DP M/N
according to current link config */ according to current link config */
...@@ -3799,6 +3794,8 @@ static int intel_crtc_mode_set(struct drm_crtc *crtc, ...@@ -3799,6 +3794,8 @@ static int intel_crtc_mode_set(struct drm_crtc *crtc,
intel_crtc->fdi_lanes = lane; 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_compute_m_n(bpp, lane, target_clock, link_bw, &m_n);
} }
...@@ -5236,6 +5233,55 @@ static const struct drm_crtc_funcs intel_crtc_funcs = { ...@@ -5236,6 +5233,55 @@ static const struct drm_crtc_funcs intel_crtc_funcs = {
.page_flip = intel_crtc_page_flip, .page_flip = intel_crtc_page_flip,
}; };
static void intel_sanitize_modesetting(struct drm_device *dev,
int pipe, int plane)
{
struct drm_i915_private *dev_priv = dev->dev_private;
u32 reg, val;
if (HAS_PCH_SPLIT(dev))
return;
/* Who knows what state these registers were left in by the BIOS or
* grub?
*
* If we leave the registers in a conflicting state (e.g. with the
* display plane reading from the other pipe than the one we intend
* to use) then when we attempt to teardown the active mode, we will
* not disable the pipes and planes in the correct order -- leaving
* a plane reading from a disabled pipe and possibly leading to
* undefined behaviour.
*/
reg = DSPCNTR(plane);
val = I915_READ(reg);
if ((val & DISPLAY_PLANE_ENABLE) == 0)
return;
if (!!(val & DISPPLANE_SEL_PIPE_MASK) == pipe)
return;
/* This display plane is active and attached to the other CPU pipe. */
pipe = !pipe;
/* Disable the plane and wait for it to stop reading from the pipe. */
I915_WRITE(reg, val & ~DISPLAY_PLANE_ENABLE);
intel_flush_display_plane(dev, plane);
if (IS_GEN2(dev))
intel_wait_for_vblank(dev, pipe);
if (pipe == 0 && (dev_priv->quirks & QUIRK_PIPEA_FORCE))
return;
/* Switch off the pipe. */
reg = PIPECONF(pipe);
val = I915_READ(reg);
if (val & PIPECONF_ENABLE) {
I915_WRITE(reg, val & ~PIPECONF_ENABLE);
intel_wait_for_pipe_off(dev, pipe);
}
}
static void intel_crtc_init(struct drm_device *dev, int pipe) static void intel_crtc_init(struct drm_device *dev, int pipe)
{ {
...@@ -5287,6 +5333,8 @@ static void intel_crtc_init(struct drm_device *dev, int pipe) ...@@ -5287,6 +5333,8 @@ static void intel_crtc_init(struct drm_device *dev, int pipe)
setup_timer(&intel_crtc->idle_timer, intel_crtc_idle_timer, setup_timer(&intel_crtc->idle_timer, intel_crtc_idle_timer,
(unsigned long)intel_crtc); (unsigned long)intel_crtc);
intel_sanitize_modesetting(dev, intel_crtc->pipe, intel_crtc->plane);
} }
int intel_get_pipe_from_crtc_id(struct drm_device *dev, void *data, int intel_get_pipe_from_crtc_id(struct drm_device *dev, void *data,
......
...@@ -1376,6 +1376,9 @@ intel_dp_link_down(struct intel_dp *intel_dp) ...@@ -1376,6 +1376,9 @@ intel_dp_link_down(struct intel_dp *intel_dp)
struct drm_i915_private *dev_priv = dev->dev_private; struct drm_i915_private *dev_priv = dev->dev_private;
uint32_t DP = intel_dp->DP; uint32_t DP = intel_dp->DP;
if ((I915_READ(intel_dp->output_reg) & DP_PORT_EN) == 0)
return;
DRM_DEBUG_KMS("\n"); DRM_DEBUG_KMS("\n");
if (is_edp(intel_dp)) { if (is_edp(intel_dp)) {
...@@ -1398,6 +1401,28 @@ intel_dp_link_down(struct intel_dp *intel_dp) ...@@ -1398,6 +1401,28 @@ intel_dp_link_down(struct intel_dp *intel_dp)
if (is_edp(intel_dp)) if (is_edp(intel_dp))
DP |= DP_LINK_TRAIN_OFF; DP |= DP_LINK_TRAIN_OFF;
if (!HAS_PCH_CPT(dev) &&
I915_READ(intel_dp->output_reg) & DP_PIPEB_SELECT) {
struct intel_crtc *intel_crtc = to_intel_crtc(intel_dp->base.base.crtc);
/* Hardware workaround: leaving our transcoder select
* set to transcoder B while it's off will prevent the
* corresponding HDMI output on transcoder A.
*
* Combine this with another hardware workaround:
* transcoder select bit can only be cleared while the
* port is enabled.
*/
DP &= ~DP_PIPEB_SELECT;
I915_WRITE(intel_dp->output_reg, DP);
/* Changes to enable or select take place the vblank
* after being written.
*/
intel_wait_for_vblank(intel_dp->base.base.dev,
intel_crtc->pipe);
}
I915_WRITE(intel_dp->output_reg, DP & ~DP_PORT_EN); I915_WRITE(intel_dp->output_reg, DP & ~DP_PORT_EN);
POSTING_READ(intel_dp->output_reg); POSTING_READ(intel_dp->output_reg);
} }
......
...@@ -68,7 +68,7 @@ static struct intel_lvds *intel_attached_lvds(struct drm_connector *connector) ...@@ -68,7 +68,7 @@ static struct intel_lvds *intel_attached_lvds(struct drm_connector *connector)
/** /**
* Sets the power state for the panel. * Sets the power state for the panel.
*/ */
static void intel_lvds_set_power(struct intel_lvds *intel_lvds, bool on) static void intel_lvds_enable(struct intel_lvds *intel_lvds)
{ {
struct drm_device *dev = intel_lvds->base.base.dev; struct drm_device *dev = intel_lvds->base.base.dev;
struct drm_i915_private *dev_priv = dev->dev_private; struct drm_i915_private *dev_priv = dev->dev_private;
...@@ -82,26 +82,61 @@ static void intel_lvds_set_power(struct intel_lvds *intel_lvds, bool on) ...@@ -82,26 +82,61 @@ static void intel_lvds_set_power(struct intel_lvds *intel_lvds, bool on)
lvds_reg = LVDS; lvds_reg = LVDS;
} }
if (on) { I915_WRITE(lvds_reg, I915_READ(lvds_reg) | LVDS_PORT_EN);
I915_WRITE(lvds_reg, I915_READ(lvds_reg) | LVDS_PORT_EN);
I915_WRITE(ctl_reg, I915_READ(ctl_reg) | POWER_TARGET_ON);
intel_panel_set_backlight(dev, dev_priv->backlight_level);
} else {
dev_priv->backlight_level = intel_panel_get_backlight(dev);
intel_panel_set_backlight(dev, 0);
I915_WRITE(ctl_reg, I915_READ(ctl_reg) & ~POWER_TARGET_ON);
if (intel_lvds->pfit_control) { if (intel_lvds->pfit_dirty) {
if (wait_for((I915_READ(PP_STATUS) & PP_ON) == 0, 1000)) /*
DRM_ERROR("timed out waiting for panel to power off\n"); * Enable automatic panel scaling so that non-native modes
I915_WRITE(PFIT_CONTROL, 0); * fill the screen. The panel fitter should only be
intel_lvds->pfit_control = 0; * adjusted whilst the pipe is disabled, according to
* register description and PRM.
*/
DRM_DEBUG_KMS("applying panel-fitter: %x, %x\n",
intel_lvds->pfit_control,
intel_lvds->pfit_pgm_ratios);
if (wait_for((I915_READ(PP_STATUS) & PP_ON) == 0, 1000)) {
DRM_ERROR("timed out waiting for panel to power off\n");
} else {
I915_WRITE(PFIT_PGM_RATIOS, intel_lvds->pfit_pgm_ratios);
I915_WRITE(PFIT_CONTROL, intel_lvds->pfit_control);
intel_lvds->pfit_dirty = false; intel_lvds->pfit_dirty = false;
} }
}
I915_WRITE(ctl_reg, I915_READ(ctl_reg) | POWER_TARGET_ON);
POSTING_READ(lvds_reg);
intel_panel_set_backlight(dev, dev_priv->backlight_level);
}
I915_WRITE(lvds_reg, I915_READ(lvds_reg) & ~LVDS_PORT_EN); static void intel_lvds_disable(struct intel_lvds *intel_lvds)
{
struct drm_device *dev = intel_lvds->base.base.dev;
struct drm_i915_private *dev_priv = dev->dev_private;
u32 ctl_reg, lvds_reg;
if (HAS_PCH_SPLIT(dev)) {
ctl_reg = PCH_PP_CONTROL;
lvds_reg = PCH_LVDS;
} else {
ctl_reg = PP_CONTROL;
lvds_reg = LVDS;
}
dev_priv->backlight_level = intel_panel_get_backlight(dev);
intel_panel_set_backlight(dev, 0);
I915_WRITE(ctl_reg, I915_READ(ctl_reg) & ~POWER_TARGET_ON);
if (intel_lvds->pfit_control) {
if (wait_for((I915_READ(PP_STATUS) & PP_ON) == 0, 1000))
DRM_ERROR("timed out waiting for panel to power off\n");
I915_WRITE(PFIT_CONTROL, 0);
intel_lvds->pfit_dirty = true;
} }
I915_WRITE(lvds_reg, I915_READ(lvds_reg) & ~LVDS_PORT_EN);
POSTING_READ(lvds_reg); POSTING_READ(lvds_reg);
} }
...@@ -110,9 +145,9 @@ static void intel_lvds_dpms(struct drm_encoder *encoder, int mode) ...@@ -110,9 +145,9 @@ static void intel_lvds_dpms(struct drm_encoder *encoder, int mode)
struct intel_lvds *intel_lvds = to_intel_lvds(encoder); struct intel_lvds *intel_lvds = to_intel_lvds(encoder);
if (mode == DRM_MODE_DPMS_ON) if (mode == DRM_MODE_DPMS_ON)
intel_lvds_set_power(intel_lvds, true); intel_lvds_enable(intel_lvds);
else else
intel_lvds_set_power(intel_lvds, false); intel_lvds_disable(intel_lvds);
/* XXX: We never power down the LVDS pairs. */ /* XXX: We never power down the LVDS pairs. */
} }
...@@ -411,43 +446,18 @@ static void intel_lvds_commit(struct drm_encoder *encoder) ...@@ -411,43 +446,18 @@ static void intel_lvds_commit(struct drm_encoder *encoder)
/* Always do a full power on as we do not know what state /* Always do a full power on as we do not know what state
* we were left in. * we were left in.
*/ */
intel_lvds_set_power(intel_lvds, true); intel_lvds_enable(intel_lvds);
} }
static void intel_lvds_mode_set(struct drm_encoder *encoder, static void intel_lvds_mode_set(struct drm_encoder *encoder,
struct drm_display_mode *mode, struct drm_display_mode *mode,
struct drm_display_mode *adjusted_mode) struct drm_display_mode *adjusted_mode)
{ {
struct drm_device *dev = encoder->dev;
struct drm_i915_private *dev_priv = dev->dev_private;
struct intel_lvds *intel_lvds = to_intel_lvds(encoder);
/* /*
* The LVDS pin pair will already have been turned on in the * The LVDS pin pair will already have been turned on in the
* intel_crtc_mode_set since it has a large impact on the DPLL * intel_crtc_mode_set since it has a large impact on the DPLL
* settings. * settings.
*/ */
if (HAS_PCH_SPLIT(dev))
return;
if (!intel_lvds->pfit_dirty)
return;
/*
* Enable automatic panel scaling so that non-native modes fill the
* screen. Should be enabled before the pipe is enabled, according to
* register description and PRM.
*/
DRM_DEBUG_KMS("applying panel-fitter: %x, %x\n",
intel_lvds->pfit_control,
intel_lvds->pfit_pgm_ratios);
if (wait_for((I915_READ(PP_STATUS) & PP_ON) == 0, 1000))
DRM_ERROR("timed out waiting for panel to power off\n");
I915_WRITE(PFIT_PGM_RATIOS, intel_lvds->pfit_pgm_ratios);
I915_WRITE(PFIT_CONTROL, intel_lvds->pfit_control);
intel_lvds->pfit_dirty = false;
} }
/** /**
......
...@@ -156,23 +156,25 @@ static int init_ring_common(struct drm_device *dev, ...@@ -156,23 +156,25 @@ static int init_ring_common(struct drm_device *dev,
/* G45 ring initialization fails to reset head to zero */ /* G45 ring initialization fails to reset head to zero */
if (head != 0) { if (head != 0) {
DRM_ERROR("%s head not reset to zero " DRM_DEBUG_KMS("%s head not reset to zero "
"ctl %08x head %08x tail %08x start %08x\n", "ctl %08x head %08x tail %08x start %08x\n",
ring->name, ring->name,
I915_READ_CTL(ring), I915_READ_CTL(ring),
I915_READ_HEAD(ring), I915_READ_HEAD(ring),
I915_READ_TAIL(ring), I915_READ_TAIL(ring),
I915_READ_START(ring)); I915_READ_START(ring));
I915_WRITE_HEAD(ring, 0); I915_WRITE_HEAD(ring, 0);
DRM_ERROR("%s head forced to zero " if (I915_READ_HEAD(ring) & HEAD_ADDR) {
"ctl %08x head %08x tail %08x start %08x\n", DRM_ERROR("failed to set %s head to zero "
ring->name, "ctl %08x head %08x tail %08x start %08x\n",
I915_READ_CTL(ring), ring->name,
I915_READ_HEAD(ring), I915_READ_CTL(ring),
I915_READ_TAIL(ring), I915_READ_HEAD(ring),
I915_READ_START(ring)); I915_READ_TAIL(ring),
I915_READ_START(ring));
}
} }
I915_WRITE_CTL(ring, I915_WRITE_CTL(ring,
......
...@@ -287,6 +287,8 @@ typedef struct drm_i915_irq_wait { ...@@ -287,6 +287,8 @@ typedef struct drm_i915_irq_wait {
#define I915_PARAM_HAS_EXECBUF2 9 #define I915_PARAM_HAS_EXECBUF2 9
#define I915_PARAM_HAS_BSD 10 #define I915_PARAM_HAS_BSD 10
#define I915_PARAM_HAS_BLT 11 #define I915_PARAM_HAS_BLT 11
#define I915_PARAM_HAS_RELAXED_FENCING 12
#define I915_PARAM_HAS_COHERENT_RINGS 13
typedef struct drm_i915_getparam { typedef struct drm_i915_getparam {
int param; int param;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment