Commit 2c24ba21 authored by Dave Airlie's avatar Dave Airlie

Merge tag 'drm-intel-fixes-2016-08-15' of git://anongit.freedesktop.org/drm-intel into drm-fixes

Collection of i915 fixes.

* tag 'drm-intel-fixes-2016-08-15' of git://anongit.freedesktop.org/drm-intel:
  drm/i915: Fix modeset handling during gpu reset, v5.
  drm/i915: fix aliasing_ppgtt leak
  drm/i915: fix WaInsertDummyPushConstPs
  drm/i915: Fix iboost setting for SKL Y/U DP DDI buffer translation entry 2
  drm/i915/gen9: Give one extra block per line for SKL plane WM calculations
  drm/i915: Acquire audio powerwell for HD-Audio registers
  drm/i915: Add missing rpm wakelock to GGTT pread
  drm/i915/fbc: FBC causes display flicker when VT-d is enabled on Skylake
  drm/i915: Clean up the extra RPM ref on CHV with i915.enable_rc6=0
  drm/i915: Program iboost settings for HDMI/DVI on SKL
  drm/i915: Fix iboost setting for DDI with 4 lanes on SKL
  drm/i915: Handle ENOSPC after failing to insert a mappable node
  drm/i915: Flush GT idle status upon reset
parents aae2d1fc dfa29970
...@@ -1854,6 +1854,7 @@ struct drm_i915_private { ...@@ -1854,6 +1854,7 @@ struct drm_i915_private {
enum modeset_restore modeset_restore; enum modeset_restore modeset_restore;
struct mutex modeset_restore_lock; struct mutex modeset_restore_lock;
struct drm_atomic_state *modeset_restore_state; struct drm_atomic_state *modeset_restore_state;
struct drm_modeset_acquire_ctx reset_ctx;
struct list_head vm_list; /* Global list of all address spaces */ struct list_head vm_list; /* Global list of all address spaces */
struct i915_ggtt ggtt; /* VM representing the global address space */ struct i915_ggtt ggtt; /* VM representing the global address space */
......
...@@ -879,9 +879,12 @@ i915_gem_pread_ioctl(struct drm_device *dev, void *data, ...@@ -879,9 +879,12 @@ i915_gem_pread_ioctl(struct drm_device *dev, void *data,
ret = i915_gem_shmem_pread(dev, obj, args, file); ret = i915_gem_shmem_pread(dev, obj, args, file);
/* pread for non shmem backed objects */ /* pread for non shmem backed objects */
if (ret == -EFAULT || ret == -ENODEV) if (ret == -EFAULT || ret == -ENODEV) {
intel_runtime_pm_get(to_i915(dev));
ret = i915_gem_gtt_pread(dev, obj, args->size, ret = i915_gem_gtt_pread(dev, obj, args->size,
args->offset, args->data_ptr); args->offset, args->data_ptr);
intel_runtime_pm_put(to_i915(dev));
}
out: out:
drm_gem_object_unreference(&obj->base); drm_gem_object_unreference(&obj->base);
...@@ -1306,7 +1309,7 @@ i915_gem_pwrite_ioctl(struct drm_device *dev, void *data, ...@@ -1306,7 +1309,7 @@ i915_gem_pwrite_ioctl(struct drm_device *dev, void *data,
* textures). Fallback to the shmem path in that case. */ * textures). Fallback to the shmem path in that case. */
} }
if (ret == -EFAULT) { if (ret == -EFAULT || ret == -ENOSPC) {
if (obj->phys_handle) if (obj->phys_handle)
ret = i915_gem_phys_pwrite(obj, args, file); ret = i915_gem_phys_pwrite(obj, args, file);
else if (i915_gem_object_has_struct_page(obj)) else if (i915_gem_object_has_struct_page(obj))
...@@ -3169,6 +3172,8 @@ static void i915_gem_reset_engine_cleanup(struct intel_engine_cs *engine) ...@@ -3169,6 +3172,8 @@ static void i915_gem_reset_engine_cleanup(struct intel_engine_cs *engine)
} }
intel_ring_init_seqno(engine, engine->last_submitted_seqno); intel_ring_init_seqno(engine, engine->last_submitted_seqno);
engine->i915->gt.active_engines &= ~intel_engine_flag(engine);
} }
void i915_gem_reset(struct drm_device *dev) void i915_gem_reset(struct drm_device *dev)
...@@ -3186,6 +3191,7 @@ void i915_gem_reset(struct drm_device *dev) ...@@ -3186,6 +3191,7 @@ void i915_gem_reset(struct drm_device *dev)
for_each_engine(engine, dev_priv) for_each_engine(engine, dev_priv)
i915_gem_reset_engine_cleanup(engine); i915_gem_reset_engine_cleanup(engine);
mod_delayed_work(dev_priv->wq, &dev_priv->gt.idle_work, 0);
i915_gem_context_reset(dev); i915_gem_context_reset(dev);
......
...@@ -2873,6 +2873,7 @@ void i915_ggtt_cleanup_hw(struct drm_device *dev) ...@@ -2873,6 +2873,7 @@ void i915_ggtt_cleanup_hw(struct drm_device *dev)
struct i915_hw_ppgtt *ppgtt = dev_priv->mm.aliasing_ppgtt; struct i915_hw_ppgtt *ppgtt = dev_priv->mm.aliasing_ppgtt;
ppgtt->base.cleanup(&ppgtt->base); ppgtt->base.cleanup(&ppgtt->base);
kfree(ppgtt);
} }
i915_gem_cleanup_stolen(dev); i915_gem_cleanup_stolen(dev);
......
...@@ -1536,6 +1536,7 @@ enum skl_disp_power_wells { ...@@ -1536,6 +1536,7 @@ enum skl_disp_power_wells {
#define BALANCE_LEG_MASK(port) (7<<(8+3*(port))) #define BALANCE_LEG_MASK(port) (7<<(8+3*(port)))
/* Balance leg disable bits */ /* Balance leg disable bits */
#define BALANCE_LEG_DISABLE_SHIFT 23 #define BALANCE_LEG_DISABLE_SHIFT 23
#define BALANCE_LEG_DISABLE(port) (1 << (23 + (port)))
/* /*
* Fence registers * Fence registers
......
...@@ -600,6 +600,8 @@ static void i915_audio_component_codec_wake_override(struct device *dev, ...@@ -600,6 +600,8 @@ static void i915_audio_component_codec_wake_override(struct device *dev,
if (!IS_SKYLAKE(dev_priv) && !IS_KABYLAKE(dev_priv)) if (!IS_SKYLAKE(dev_priv) && !IS_KABYLAKE(dev_priv))
return; return;
i915_audio_component_get_power(dev);
/* /*
* Enable/disable generating the codec wake signal, overriding the * Enable/disable generating the codec wake signal, overriding the
* internal logic to generate the codec wake to controller. * internal logic to generate the codec wake to controller.
...@@ -615,6 +617,8 @@ static void i915_audio_component_codec_wake_override(struct device *dev, ...@@ -615,6 +617,8 @@ static void i915_audio_component_codec_wake_override(struct device *dev,
I915_WRITE(HSW_AUD_CHICKENBIT, tmp); I915_WRITE(HSW_AUD_CHICKENBIT, tmp);
usleep_range(1000, 1500); usleep_range(1000, 1500);
} }
i915_audio_component_put_power(dev);
} }
/* Get CDCLK in kHz */ /* Get CDCLK in kHz */
...@@ -648,6 +652,7 @@ static int i915_audio_component_sync_audio_rate(struct device *dev, ...@@ -648,6 +652,7 @@ static int i915_audio_component_sync_audio_rate(struct device *dev,
!IS_HASWELL(dev_priv)) !IS_HASWELL(dev_priv))
return 0; return 0;
i915_audio_component_get_power(dev);
mutex_lock(&dev_priv->av_mutex); mutex_lock(&dev_priv->av_mutex);
/* 1. get the pipe */ /* 1. get the pipe */
intel_encoder = dev_priv->dig_port_map[port]; intel_encoder = dev_priv->dig_port_map[port];
...@@ -698,6 +703,7 @@ static int i915_audio_component_sync_audio_rate(struct device *dev, ...@@ -698,6 +703,7 @@ static int i915_audio_component_sync_audio_rate(struct device *dev,
unlock: unlock:
mutex_unlock(&dev_priv->av_mutex); mutex_unlock(&dev_priv->av_mutex);
i915_audio_component_put_power(dev);
return err; return err;
} }
......
...@@ -145,7 +145,7 @@ static const struct ddi_buf_trans skl_ddi_translations_dp[] = { ...@@ -145,7 +145,7 @@ static const struct ddi_buf_trans skl_ddi_translations_dp[] = {
static const struct ddi_buf_trans skl_u_ddi_translations_dp[] = { static const struct ddi_buf_trans skl_u_ddi_translations_dp[] = {
{ 0x0000201B, 0x000000A2, 0x0 }, { 0x0000201B, 0x000000A2, 0x0 },
{ 0x00005012, 0x00000088, 0x0 }, { 0x00005012, 0x00000088, 0x0 },
{ 0x80007011, 0x000000CD, 0x0 }, { 0x80007011, 0x000000CD, 0x1 },
{ 0x80009010, 0x000000C0, 0x1 }, { 0x80009010, 0x000000C0, 0x1 },
{ 0x0000201B, 0x0000009D, 0x0 }, { 0x0000201B, 0x0000009D, 0x0 },
{ 0x80005012, 0x000000C0, 0x1 }, { 0x80005012, 0x000000C0, 0x1 },
...@@ -158,7 +158,7 @@ static const struct ddi_buf_trans skl_u_ddi_translations_dp[] = { ...@@ -158,7 +158,7 @@ static const struct ddi_buf_trans skl_u_ddi_translations_dp[] = {
static const struct ddi_buf_trans skl_y_ddi_translations_dp[] = { static const struct ddi_buf_trans skl_y_ddi_translations_dp[] = {
{ 0x00000018, 0x000000A2, 0x0 }, { 0x00000018, 0x000000A2, 0x0 },
{ 0x00005012, 0x00000088, 0x0 }, { 0x00005012, 0x00000088, 0x0 },
{ 0x80007011, 0x000000CD, 0x0 }, { 0x80007011, 0x000000CD, 0x3 },
{ 0x80009010, 0x000000C0, 0x3 }, { 0x80009010, 0x000000C0, 0x3 },
{ 0x00000018, 0x0000009D, 0x0 }, { 0x00000018, 0x0000009D, 0x0 },
{ 0x80005012, 0x000000C0, 0x3 }, { 0x80005012, 0x000000C0, 0x3 },
...@@ -388,6 +388,40 @@ skl_get_buf_trans_hdmi(struct drm_i915_private *dev_priv, int *n_entries) ...@@ -388,6 +388,40 @@ skl_get_buf_trans_hdmi(struct drm_i915_private *dev_priv, int *n_entries)
} }
} }
static int intel_ddi_hdmi_level(struct drm_i915_private *dev_priv, enum port port)
{
int n_hdmi_entries;
int hdmi_level;
int hdmi_default_entry;
hdmi_level = dev_priv->vbt.ddi_port_info[port].hdmi_level_shift;
if (IS_BROXTON(dev_priv))
return hdmi_level;
if (IS_SKYLAKE(dev_priv) || IS_KABYLAKE(dev_priv)) {
skl_get_buf_trans_hdmi(dev_priv, &n_hdmi_entries);
hdmi_default_entry = 8;
} else if (IS_BROADWELL(dev_priv)) {
n_hdmi_entries = ARRAY_SIZE(bdw_ddi_translations_hdmi);
hdmi_default_entry = 7;
} else if (IS_HASWELL(dev_priv)) {
n_hdmi_entries = ARRAY_SIZE(hsw_ddi_translations_hdmi);
hdmi_default_entry = 6;
} else {
WARN(1, "ddi translation table missing\n");
n_hdmi_entries = ARRAY_SIZE(bdw_ddi_translations_hdmi);
hdmi_default_entry = 7;
}
/* Choose a good default if VBT is badly populated */
if (hdmi_level == HDMI_LEVEL_SHIFT_UNKNOWN ||
hdmi_level >= n_hdmi_entries)
hdmi_level = hdmi_default_entry;
return hdmi_level;
}
/* /*
* Starting with Haswell, DDI port buffers must be programmed with correct * Starting with Haswell, DDI port buffers must be programmed with correct
* values in advance. The buffer values are different for FDI and DP modes, * values in advance. The buffer values are different for FDI and DP modes,
...@@ -399,7 +433,7 @@ void intel_prepare_ddi_buffer(struct intel_encoder *encoder) ...@@ -399,7 +433,7 @@ void intel_prepare_ddi_buffer(struct intel_encoder *encoder)
{ {
struct drm_i915_private *dev_priv = to_i915(encoder->base.dev); struct drm_i915_private *dev_priv = to_i915(encoder->base.dev);
u32 iboost_bit = 0; u32 iboost_bit = 0;
int i, n_hdmi_entries, n_dp_entries, n_edp_entries, hdmi_default_entry, int i, n_hdmi_entries, n_dp_entries, n_edp_entries,
size; size;
int hdmi_level; int hdmi_level;
enum port port; enum port port;
...@@ -410,7 +444,7 @@ void intel_prepare_ddi_buffer(struct intel_encoder *encoder) ...@@ -410,7 +444,7 @@ void intel_prepare_ddi_buffer(struct intel_encoder *encoder)
const struct ddi_buf_trans *ddi_translations; const struct ddi_buf_trans *ddi_translations;
port = intel_ddi_get_encoder_port(encoder); port = intel_ddi_get_encoder_port(encoder);
hdmi_level = dev_priv->vbt.ddi_port_info[port].hdmi_level_shift; hdmi_level = intel_ddi_hdmi_level(dev_priv, port);
if (IS_BROXTON(dev_priv)) { if (IS_BROXTON(dev_priv)) {
if (encoder->type != INTEL_OUTPUT_HDMI) if (encoder->type != INTEL_OUTPUT_HDMI)
...@@ -430,7 +464,6 @@ void intel_prepare_ddi_buffer(struct intel_encoder *encoder) ...@@ -430,7 +464,6 @@ void intel_prepare_ddi_buffer(struct intel_encoder *encoder)
skl_get_buf_trans_edp(dev_priv, &n_edp_entries); skl_get_buf_trans_edp(dev_priv, &n_edp_entries);
ddi_translations_hdmi = ddi_translations_hdmi =
skl_get_buf_trans_hdmi(dev_priv, &n_hdmi_entries); skl_get_buf_trans_hdmi(dev_priv, &n_hdmi_entries);
hdmi_default_entry = 8;
/* If we're boosting the current, set bit 31 of trans1 */ /* If we're boosting the current, set bit 31 of trans1 */
if (dev_priv->vbt.ddi_port_info[port].hdmi_boost_level || if (dev_priv->vbt.ddi_port_info[port].hdmi_boost_level ||
dev_priv->vbt.ddi_port_info[port].dp_boost_level) dev_priv->vbt.ddi_port_info[port].dp_boost_level)
...@@ -456,7 +489,6 @@ void intel_prepare_ddi_buffer(struct intel_encoder *encoder) ...@@ -456,7 +489,6 @@ void intel_prepare_ddi_buffer(struct intel_encoder *encoder)
n_dp_entries = ARRAY_SIZE(bdw_ddi_translations_dp); n_dp_entries = ARRAY_SIZE(bdw_ddi_translations_dp);
n_hdmi_entries = ARRAY_SIZE(bdw_ddi_translations_hdmi); n_hdmi_entries = ARRAY_SIZE(bdw_ddi_translations_hdmi);
hdmi_default_entry = 7;
} else if (IS_HASWELL(dev_priv)) { } else if (IS_HASWELL(dev_priv)) {
ddi_translations_fdi = hsw_ddi_translations_fdi; ddi_translations_fdi = hsw_ddi_translations_fdi;
ddi_translations_dp = hsw_ddi_translations_dp; ddi_translations_dp = hsw_ddi_translations_dp;
...@@ -464,7 +496,6 @@ void intel_prepare_ddi_buffer(struct intel_encoder *encoder) ...@@ -464,7 +496,6 @@ void intel_prepare_ddi_buffer(struct intel_encoder *encoder)
ddi_translations_hdmi = hsw_ddi_translations_hdmi; ddi_translations_hdmi = hsw_ddi_translations_hdmi;
n_dp_entries = n_edp_entries = ARRAY_SIZE(hsw_ddi_translations_dp); n_dp_entries = n_edp_entries = ARRAY_SIZE(hsw_ddi_translations_dp);
n_hdmi_entries = ARRAY_SIZE(hsw_ddi_translations_hdmi); n_hdmi_entries = ARRAY_SIZE(hsw_ddi_translations_hdmi);
hdmi_default_entry = 6;
} else { } else {
WARN(1, "ddi translation table missing\n"); WARN(1, "ddi translation table missing\n");
ddi_translations_edp = bdw_ddi_translations_dp; ddi_translations_edp = bdw_ddi_translations_dp;
...@@ -474,7 +505,6 @@ void intel_prepare_ddi_buffer(struct intel_encoder *encoder) ...@@ -474,7 +505,6 @@ void intel_prepare_ddi_buffer(struct intel_encoder *encoder)
n_edp_entries = ARRAY_SIZE(bdw_ddi_translations_edp); n_edp_entries = ARRAY_SIZE(bdw_ddi_translations_edp);
n_dp_entries = ARRAY_SIZE(bdw_ddi_translations_dp); n_dp_entries = ARRAY_SIZE(bdw_ddi_translations_dp);
n_hdmi_entries = ARRAY_SIZE(bdw_ddi_translations_hdmi); n_hdmi_entries = ARRAY_SIZE(bdw_ddi_translations_hdmi);
hdmi_default_entry = 7;
} }
switch (encoder->type) { switch (encoder->type) {
...@@ -505,11 +535,6 @@ void intel_prepare_ddi_buffer(struct intel_encoder *encoder) ...@@ -505,11 +535,6 @@ void intel_prepare_ddi_buffer(struct intel_encoder *encoder)
if (encoder->type != INTEL_OUTPUT_HDMI) if (encoder->type != INTEL_OUTPUT_HDMI)
return; return;
/* Choose a good default if VBT is badly populated */
if (hdmi_level == HDMI_LEVEL_SHIFT_UNKNOWN ||
hdmi_level >= n_hdmi_entries)
hdmi_level = hdmi_default_entry;
/* Entry 9 is for HDMI: */ /* Entry 9 is for HDMI: */
I915_WRITE(DDI_BUF_TRANS_LO(port, i), I915_WRITE(DDI_BUF_TRANS_LO(port, i),
ddi_translations_hdmi[hdmi_level].trans1 | iboost_bit); ddi_translations_hdmi[hdmi_level].trans1 | iboost_bit);
...@@ -1379,14 +1404,30 @@ void intel_ddi_disable_pipe_clock(struct intel_crtc *intel_crtc) ...@@ -1379,14 +1404,30 @@ void intel_ddi_disable_pipe_clock(struct intel_crtc *intel_crtc)
TRANS_CLK_SEL_DISABLED); TRANS_CLK_SEL_DISABLED);
} }
static void skl_ddi_set_iboost(struct drm_i915_private *dev_priv, static void _skl_ddi_set_iboost(struct drm_i915_private *dev_priv,
u32 level, enum port port, int type) enum port port, uint8_t iboost)
{ {
u32 tmp;
tmp = I915_READ(DISPIO_CR_TX_BMU_CR0);
tmp &= ~(BALANCE_LEG_MASK(port) | BALANCE_LEG_DISABLE(port));
if (iboost)
tmp |= iboost << BALANCE_LEG_SHIFT(port);
else
tmp |= BALANCE_LEG_DISABLE(port);
I915_WRITE(DISPIO_CR_TX_BMU_CR0, tmp);
}
static void skl_ddi_set_iboost(struct intel_encoder *encoder, u32 level)
{
struct intel_digital_port *intel_dig_port = enc_to_dig_port(&encoder->base);
struct drm_i915_private *dev_priv = to_i915(intel_dig_port->base.base.dev);
enum port port = intel_dig_port->port;
int type = encoder->type;
const struct ddi_buf_trans *ddi_translations; const struct ddi_buf_trans *ddi_translations;
uint8_t iboost; uint8_t iboost;
uint8_t dp_iboost, hdmi_iboost; uint8_t dp_iboost, hdmi_iboost;
int n_entries; int n_entries;
u32 reg;
/* VBT may override standard boost values */ /* VBT may override standard boost values */
dp_iboost = dev_priv->vbt.ddi_port_info[port].dp_boost_level; dp_iboost = dev_priv->vbt.ddi_port_info[port].dp_boost_level;
...@@ -1428,16 +1469,10 @@ static void skl_ddi_set_iboost(struct drm_i915_private *dev_priv, ...@@ -1428,16 +1469,10 @@ static void skl_ddi_set_iboost(struct drm_i915_private *dev_priv,
return; return;
} }
reg = I915_READ(DISPIO_CR_TX_BMU_CR0); _skl_ddi_set_iboost(dev_priv, port, iboost);
reg &= ~BALANCE_LEG_MASK(port);
reg &= ~(1 << (BALANCE_LEG_DISABLE_SHIFT + port));
if (iboost)
reg |= iboost << BALANCE_LEG_SHIFT(port);
else
reg |= 1 << (BALANCE_LEG_DISABLE_SHIFT + port);
I915_WRITE(DISPIO_CR_TX_BMU_CR0, reg); if (port == PORT_A && intel_dig_port->max_lanes == 4)
_skl_ddi_set_iboost(dev_priv, PORT_E, iboost);
} }
static void bxt_ddi_vswing_sequence(struct drm_i915_private *dev_priv, static void bxt_ddi_vswing_sequence(struct drm_i915_private *dev_priv,
...@@ -1568,7 +1603,7 @@ uint32_t ddi_signal_levels(struct intel_dp *intel_dp) ...@@ -1568,7 +1603,7 @@ uint32_t ddi_signal_levels(struct intel_dp *intel_dp)
level = translate_signal_level(signal_levels); level = translate_signal_level(signal_levels);
if (IS_SKYLAKE(dev_priv) || IS_KABYLAKE(dev_priv)) if (IS_SKYLAKE(dev_priv) || IS_KABYLAKE(dev_priv))
skl_ddi_set_iboost(dev_priv, level, port, encoder->type); skl_ddi_set_iboost(encoder, level);
else if (IS_BROXTON(dev_priv)) else if (IS_BROXTON(dev_priv))
bxt_ddi_vswing_sequence(dev_priv, level, port, encoder->type); bxt_ddi_vswing_sequence(dev_priv, level, port, encoder->type);
...@@ -1637,6 +1672,10 @@ static void intel_ddi_pre_enable(struct intel_encoder *intel_encoder) ...@@ -1637,6 +1672,10 @@ static void intel_ddi_pre_enable(struct intel_encoder *intel_encoder)
intel_dp_stop_link_train(intel_dp); intel_dp_stop_link_train(intel_dp);
} else if (type == INTEL_OUTPUT_HDMI) { } else if (type == INTEL_OUTPUT_HDMI) {
struct intel_hdmi *intel_hdmi = enc_to_intel_hdmi(encoder); struct intel_hdmi *intel_hdmi = enc_to_intel_hdmi(encoder);
int level = intel_ddi_hdmi_level(dev_priv, port);
if (IS_SKYLAKE(dev_priv) || IS_KABYLAKE(dev_priv))
skl_ddi_set_iboost(intel_encoder, level);
intel_hdmi->set_infoframes(encoder, intel_hdmi->set_infoframes(encoder,
crtc->config->has_hdmi_sink, crtc->config->has_hdmi_sink,
......
...@@ -3093,40 +3093,110 @@ static void intel_update_primary_planes(struct drm_device *dev) ...@@ -3093,40 +3093,110 @@ static void intel_update_primary_planes(struct drm_device *dev)
for_each_crtc(dev, crtc) { for_each_crtc(dev, crtc) {
struct intel_plane *plane = to_intel_plane(crtc->primary); struct intel_plane *plane = to_intel_plane(crtc->primary);
struct intel_plane_state *plane_state; struct intel_plane_state *plane_state =
to_intel_plane_state(plane->base.state);
drm_modeset_lock_crtc(crtc, &plane->base);
plane_state = to_intel_plane_state(plane->base.state);
if (plane_state->visible) if (plane_state->visible)
plane->update_plane(&plane->base, plane->update_plane(&plane->base,
to_intel_crtc_state(crtc->state), to_intel_crtc_state(crtc->state),
plane_state); plane_state);
}
}
static int
__intel_display_resume(struct drm_device *dev,
struct drm_atomic_state *state)
{
struct drm_crtc_state *crtc_state;
struct drm_crtc *crtc;
int i, ret;
intel_modeset_setup_hw_state(dev);
i915_redisable_vga(dev);
drm_modeset_unlock_crtc(crtc); if (!state)
return 0;
for_each_crtc_in_state(state, crtc, crtc_state, i) {
/*
* Force recalculation even if we restore
* current state. With fast modeset this may not result
* in a modeset when the state is compatible.
*/
crtc_state->mode_changed = true;
} }
/* ignore any reset values/BIOS leftovers in the WM registers */
to_intel_atomic_state(state)->skip_intermediate_wm = true;
ret = drm_atomic_commit(state);
WARN_ON(ret == -EDEADLK);
return ret;
} }
void intel_prepare_reset(struct drm_i915_private *dev_priv) void intel_prepare_reset(struct drm_i915_private *dev_priv)
{ {
struct drm_device *dev = &dev_priv->drm;
struct drm_modeset_acquire_ctx *ctx = &dev_priv->reset_ctx;
struct drm_atomic_state *state;
int ret;
/* no reset support for gen2 */ /* no reset support for gen2 */
if (IS_GEN2(dev_priv)) if (IS_GEN2(dev_priv))
return; return;
/* reset doesn't touch the display */ /*
* Need mode_config.mutex so that we don't
* trample ongoing ->detect() and whatnot.
*/
mutex_lock(&dev->mode_config.mutex);
drm_modeset_acquire_init(ctx, 0);
while (1) {
ret = drm_modeset_lock_all_ctx(dev, ctx);
if (ret != -EDEADLK)
break;
drm_modeset_backoff(ctx);
}
/* reset doesn't touch the display, but flips might get nuked anyway, */
if (INTEL_GEN(dev_priv) >= 5 || IS_G4X(dev_priv)) if (INTEL_GEN(dev_priv) >= 5 || IS_G4X(dev_priv))
return; return;
drm_modeset_lock_all(&dev_priv->drm);
/* /*
* Disabling the crtcs gracefully seems nicer. Also the * Disabling the crtcs gracefully seems nicer. Also the
* g33 docs say we should at least disable all the planes. * g33 docs say we should at least disable all the planes.
*/ */
intel_display_suspend(&dev_priv->drm); state = drm_atomic_helper_duplicate_state(dev, ctx);
if (IS_ERR(state)) {
ret = PTR_ERR(state);
state = NULL;
DRM_ERROR("Duplicating state failed with %i\n", ret);
goto err;
}
ret = drm_atomic_helper_disable_all(dev, ctx);
if (ret) {
DRM_ERROR("Suspending crtc's failed with %i\n", ret);
goto err;
}
dev_priv->modeset_restore_state = state;
state->acquire_ctx = ctx;
return;
err:
drm_atomic_state_free(state);
} }
void intel_finish_reset(struct drm_i915_private *dev_priv) void intel_finish_reset(struct drm_i915_private *dev_priv)
{ {
struct drm_device *dev = &dev_priv->drm;
struct drm_modeset_acquire_ctx *ctx = &dev_priv->reset_ctx;
struct drm_atomic_state *state = dev_priv->modeset_restore_state;
int ret;
/* /*
* Flips in the rings will be nuked by the reset, * Flips in the rings will be nuked by the reset,
* so complete all pending flips so that user space * so complete all pending flips so that user space
...@@ -3138,6 +3208,8 @@ void intel_finish_reset(struct drm_i915_private *dev_priv) ...@@ -3138,6 +3208,8 @@ void intel_finish_reset(struct drm_i915_private *dev_priv)
if (IS_GEN2(dev_priv)) if (IS_GEN2(dev_priv))
return; return;
dev_priv->modeset_restore_state = NULL;
/* reset doesn't touch the display */ /* reset doesn't touch the display */
if (INTEL_GEN(dev_priv) >= 5 || IS_G4X(dev_priv)) { if (INTEL_GEN(dev_priv) >= 5 || IS_G4X(dev_priv)) {
/* /*
...@@ -3149,10 +3221,8 @@ void intel_finish_reset(struct drm_i915_private *dev_priv) ...@@ -3149,10 +3221,8 @@ void intel_finish_reset(struct drm_i915_private *dev_priv)
* FIXME: Atomic will make this obsolete since we won't schedule * FIXME: Atomic will make this obsolete since we won't schedule
* CS-based flips (which might get lost in gpu resets) any more. * CS-based flips (which might get lost in gpu resets) any more.
*/ */
intel_update_primary_planes(&dev_priv->drm); intel_update_primary_planes(dev);
return; } else {
}
/* /*
* The display has been reset as well, * The display has been reset as well,
* so need a full re-initialization. * so need a full re-initialization.
...@@ -3160,18 +3230,23 @@ void intel_finish_reset(struct drm_i915_private *dev_priv) ...@@ -3160,18 +3230,23 @@ void intel_finish_reset(struct drm_i915_private *dev_priv)
intel_runtime_pm_disable_interrupts(dev_priv); intel_runtime_pm_disable_interrupts(dev_priv);
intel_runtime_pm_enable_interrupts(dev_priv); intel_runtime_pm_enable_interrupts(dev_priv);
intel_modeset_init_hw(&dev_priv->drm); intel_modeset_init_hw(dev);
spin_lock_irq(&dev_priv->irq_lock); spin_lock_irq(&dev_priv->irq_lock);
if (dev_priv->display.hpd_irq_setup) if (dev_priv->display.hpd_irq_setup)
dev_priv->display.hpd_irq_setup(dev_priv); dev_priv->display.hpd_irq_setup(dev_priv);
spin_unlock_irq(&dev_priv->irq_lock); spin_unlock_irq(&dev_priv->irq_lock);
intel_display_resume(&dev_priv->drm); ret = __intel_display_resume(dev, state);
if (ret)
DRM_ERROR("Restoring old state failed with %i\n", ret);
intel_hpd_init(dev_priv); intel_hpd_init(dev_priv);
}
drm_modeset_unlock_all(&dev_priv->drm); drm_modeset_drop_locks(ctx);
drm_modeset_acquire_fini(ctx);
mutex_unlock(&dev->mode_config.mutex);
} }
static bool intel_crtc_has_pending_flip(struct drm_crtc *crtc) static bool intel_crtc_has_pending_flip(struct drm_crtc *crtc)
...@@ -16156,9 +16231,10 @@ void intel_display_resume(struct drm_device *dev) ...@@ -16156,9 +16231,10 @@ void intel_display_resume(struct drm_device *dev)
struct drm_atomic_state *state = dev_priv->modeset_restore_state; struct drm_atomic_state *state = dev_priv->modeset_restore_state;
struct drm_modeset_acquire_ctx ctx; struct drm_modeset_acquire_ctx ctx;
int ret; int ret;
bool setup = false;
dev_priv->modeset_restore_state = NULL; dev_priv->modeset_restore_state = NULL;
if (state)
state->acquire_ctx = &ctx;
/* /*
* This is a cludge because with real atomic modeset mode_config.mutex * This is a cludge because with real atomic modeset mode_config.mutex
...@@ -16169,43 +16245,17 @@ void intel_display_resume(struct drm_device *dev) ...@@ -16169,43 +16245,17 @@ void intel_display_resume(struct drm_device *dev)
mutex_lock(&dev->mode_config.mutex); mutex_lock(&dev->mode_config.mutex);
drm_modeset_acquire_init(&ctx, 0); drm_modeset_acquire_init(&ctx, 0);
retry: while (1) {
ret = drm_modeset_lock_all_ctx(dev, &ctx); ret = drm_modeset_lock_all_ctx(dev, &ctx);
if (ret != -EDEADLK)
break;
if (ret == 0 && !setup) {
setup = true;
intel_modeset_setup_hw_state(dev);
i915_redisable_vga(dev);
}
if (ret == 0 && state) {
struct drm_crtc_state *crtc_state;
struct drm_crtc *crtc;
int i;
state->acquire_ctx = &ctx;
/* ignore any reset values/BIOS leftovers in the WM registers */
to_intel_atomic_state(state)->skip_intermediate_wm = true;
for_each_crtc_in_state(state, crtc, crtc_state, i) {
/*
* Force recalculation even if we restore
* current state. With fast modeset this may not result
* in a modeset when the state is compatible.
*/
crtc_state->mode_changed = true;
}
ret = drm_atomic_commit(state);
}
if (ret == -EDEADLK) {
drm_modeset_backoff(&ctx); drm_modeset_backoff(&ctx);
goto retry;
} }
if (!ret)
ret = __intel_display_resume(dev, state);
drm_modeset_drop_locks(&ctx); drm_modeset_drop_locks(&ctx);
drm_modeset_acquire_fini(&ctx); drm_modeset_acquire_fini(&ctx);
mutex_unlock(&dev->mode_config.mutex); mutex_unlock(&dev->mode_config.mutex);
......
...@@ -1230,12 +1230,29 @@ static int intel_sanitize_fbc_option(struct drm_i915_private *dev_priv) ...@@ -1230,12 +1230,29 @@ static int intel_sanitize_fbc_option(struct drm_i915_private *dev_priv)
if (i915.enable_fbc >= 0) if (i915.enable_fbc >= 0)
return !!i915.enable_fbc; return !!i915.enable_fbc;
if (!HAS_FBC(dev_priv))
return 0;
if (IS_BROADWELL(dev_priv)) if (IS_BROADWELL(dev_priv))
return 1; return 1;
return 0; return 0;
} }
static bool need_fbc_vtd_wa(struct drm_i915_private *dev_priv)
{
#ifdef CONFIG_INTEL_IOMMU
/* WaFbcTurnOffFbcWhenHyperVisorIsUsed:skl,bxt */
if (intel_iommu_gfx_mapped &&
(IS_SKYLAKE(dev_priv) || IS_BROXTON(dev_priv))) {
DRM_INFO("Disabling framebuffer compression (FBC) to prevent screen flicker with VT-d enabled\n");
return true;
}
#endif
return false;
}
/** /**
* intel_fbc_init - Initialize FBC * intel_fbc_init - Initialize FBC
* @dev_priv: the i915 device * @dev_priv: the i915 device
...@@ -1253,6 +1270,9 @@ void intel_fbc_init(struct drm_i915_private *dev_priv) ...@@ -1253,6 +1270,9 @@ void intel_fbc_init(struct drm_i915_private *dev_priv)
fbc->active = false; fbc->active = false;
fbc->work.scheduled = false; fbc->work.scheduled = false;
if (need_fbc_vtd_wa(dev_priv))
mkwrite_device_info(dev_priv)->has_fbc = false;
i915.enable_fbc = intel_sanitize_fbc_option(dev_priv); i915.enable_fbc = intel_sanitize_fbc_option(dev_priv);
DRM_DEBUG_KMS("Sanitized enable_fbc value: %d\n", i915.enable_fbc); DRM_DEBUG_KMS("Sanitized enable_fbc value: %d\n", i915.enable_fbc);
......
...@@ -3344,6 +3344,8 @@ static uint32_t skl_wm_method2(uint32_t pixel_rate, uint32_t pipe_htotal, ...@@ -3344,6 +3344,8 @@ static uint32_t skl_wm_method2(uint32_t pixel_rate, uint32_t pipe_htotal,
plane_bytes_per_line *= 4; plane_bytes_per_line *= 4;
plane_blocks_per_line = DIV_ROUND_UP(plane_bytes_per_line, 512); plane_blocks_per_line = DIV_ROUND_UP(plane_bytes_per_line, 512);
plane_blocks_per_line /= 4; plane_blocks_per_line /= 4;
} else if (tiling == DRM_FORMAT_MOD_NONE) {
plane_blocks_per_line = DIV_ROUND_UP(plane_bytes_per_line, 512) + 1;
} else { } else {
plane_blocks_per_line = DIV_ROUND_UP(plane_bytes_per_line, 512); plane_blocks_per_line = DIV_ROUND_UP(plane_bytes_per_line, 512);
} }
...@@ -6574,9 +6576,7 @@ void intel_init_gt_powersave(struct drm_i915_private *dev_priv) ...@@ -6574,9 +6576,7 @@ void intel_init_gt_powersave(struct drm_i915_private *dev_priv)
void intel_cleanup_gt_powersave(struct drm_i915_private *dev_priv) void intel_cleanup_gt_powersave(struct drm_i915_private *dev_priv)
{ {
if (IS_CHERRYVIEW(dev_priv)) if (IS_VALLEYVIEW(dev_priv))
return;
else if (IS_VALLEYVIEW(dev_priv))
valleyview_cleanup_gt_powersave(dev_priv); valleyview_cleanup_gt_powersave(dev_priv);
if (!i915.enable_rc6) if (!i915.enable_rc6)
......
...@@ -1178,8 +1178,8 @@ static int bxt_init_workarounds(struct intel_engine_cs *engine) ...@@ -1178,8 +1178,8 @@ static int bxt_init_workarounds(struct intel_engine_cs *engine)
I915_WRITE(GEN8_L3SQCREG1, L3_GENERAL_PRIO_CREDITS(62) | I915_WRITE(GEN8_L3SQCREG1, L3_GENERAL_PRIO_CREDITS(62) |
L3_HIGH_PRIO_CREDITS(2)); L3_HIGH_PRIO_CREDITS(2));
/* WaInsertDummyPushConstPs:bxt */ /* WaToEnableHwFixForPushConstHWBug:bxt */
if (IS_BXT_REVID(dev_priv, 0, BXT_REVID_B0)) if (IS_BXT_REVID(dev_priv, BXT_REVID_C0, REVID_FOREVER))
WA_SET_BIT_MASKED(COMMON_SLICE_CHICKEN2, WA_SET_BIT_MASKED(COMMON_SLICE_CHICKEN2,
GEN8_SBE_DISABLE_REPLAY_BUF_OPTIMIZATION); GEN8_SBE_DISABLE_REPLAY_BUF_OPTIMIZATION);
...@@ -1222,8 +1222,8 @@ static int kbl_init_workarounds(struct intel_engine_cs *engine) ...@@ -1222,8 +1222,8 @@ static int kbl_init_workarounds(struct intel_engine_cs *engine)
I915_WRITE(GEN8_L3SQCREG4, I915_READ(GEN8_L3SQCREG4) | I915_WRITE(GEN8_L3SQCREG4, I915_READ(GEN8_L3SQCREG4) |
GEN8_LQSC_RO_PERF_DIS); GEN8_LQSC_RO_PERF_DIS);
/* WaInsertDummyPushConstPs:kbl */ /* WaToEnableHwFixForPushConstHWBug:kbl */
if (IS_KBL_REVID(dev_priv, 0, KBL_REVID_B0)) if (IS_KBL_REVID(dev_priv, KBL_REVID_C0, REVID_FOREVER))
WA_SET_BIT_MASKED(COMMON_SLICE_CHICKEN2, WA_SET_BIT_MASKED(COMMON_SLICE_CHICKEN2,
GEN8_SBE_DISABLE_REPLAY_BUF_OPTIMIZATION); GEN8_SBE_DISABLE_REPLAY_BUF_OPTIMIZATION);
......
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