mirror of
https://github.com/torvalds/linux.git
synced 2024-12-27 05:11:48 +00:00
Merge tag 'drm-intel-fixes-2014-08-08' of git://anongit.freedesktop.org/drm-intel
Pull intel drm fixes from Daniel Vetter: "So I heard that proper pull requests have a revert on top ;-) So here we go with my usual mid-merge-window pile of fixes. [ Ed. This revert thing had better not become the "in" thing ] Big fix is the duct-tape for ring init on g4x platforms, we seem to have found the magic again to make those machines as happy as before (not perfect though unfortunately, but that was never the case). Otherwise fixes all over: - tune down some overzealous debug output - VDD power sequencing fix after resume - bunch of dsi fixes for baytrail among them hw state checker de-noising - bunch of error state capture fixes for bdw - misc tiny fixes/workarounds for various platforms Last minute rebase was to kick out two patches that shouldn't have been in here - they're for the state checker, so 0 functional code affected. Jani's back from vacation, so he'll take over -fixes from here" * tag 'drm-intel-fixes-2014-08-08' of git://anongit.freedesktop.org/drm-intel: (21 commits) Revert "drm/i915: Enable semaphores on BDW" drm/i915: read HEAD register back in init_ring_common() to enforce ordering drm/i915: Fix crash when failing to parse MIPI VBT drm/i915: Bring GPU Freq to min while suspending. drm/i915: Fix DEIER and GTIER collecting for BDW. drm/i915: Don't accumulate hangcheck score on forward progress drm/i915: Add the WaCsStallBeforeStateCacheInvalidate:bdw workaround. drm/i915: Refactor Broadwell PIPE_CONTROL emission into a helper. drm/i915: Fix threshold for choosing 32 vs. 64 precisions for VLV DDL values drm/i915: Fix drain latency precision multipler for VLV drm/i915: Collect gtier properly on HSW. drm/i915: Tune down MCH_SSKPD values warning drm/i915: Tune done rc6 enabling output drm/i915: Don't require dev->struct_mutex in psr_match_conditions drm/i915: Fix error state collecting drm/i915: fix VDD state tracking after system resume drm/i915: Add correct hw/sw config check for DSI encoder drm/i915: factor out intel_edp_panel_vdd_sanitize drm/i915: wait for all DSI FIFOs to be empty drm/i915: work around warning in i915_gem_gtt ...
This commit is contained in:
commit
889fa782bf
@ -481,6 +481,10 @@ bool i915_semaphore_is_enabled(struct drm_device *dev)
|
||||
if (i915.semaphores >= 0)
|
||||
return i915.semaphores;
|
||||
|
||||
/* Until we get further testing... */
|
||||
if (IS_GEN8(dev))
|
||||
return false;
|
||||
|
||||
#ifdef CONFIG_INTEL_IOMMU
|
||||
/* Enable semaphores on SNB when IO remapping is off */
|
||||
if (INTEL_INFO(dev)->gen == 6 && intel_iommu_gfx_mapped)
|
||||
|
@ -53,7 +53,7 @@
|
||||
|
||||
#define DRIVER_NAME "i915"
|
||||
#define DRIVER_DESC "Intel Graphics"
|
||||
#define DRIVER_DATE "20140620"
|
||||
#define DRIVER_DATE "20140725"
|
||||
|
||||
enum pipe {
|
||||
INVALID_PIPE = -1,
|
||||
@ -314,6 +314,7 @@ struct drm_i915_error_state {
|
||||
u32 eir;
|
||||
u32 pgtbl_er;
|
||||
u32 ier;
|
||||
u32 gtier[4];
|
||||
u32 ccid;
|
||||
u32 derrmr;
|
||||
u32 forcewake;
|
||||
|
@ -4545,7 +4545,7 @@ i915_gem_suspend(struct drm_device *dev)
|
||||
|
||||
del_timer_sync(&dev_priv->gpu_error.hangcheck_timer);
|
||||
cancel_delayed_work_sync(&dev_priv->mm.retire_work);
|
||||
cancel_delayed_work_sync(&dev_priv->mm.idle_work);
|
||||
flush_delayed_work(&dev_priv->mm.idle_work);
|
||||
|
||||
return 0;
|
||||
|
||||
|
@ -1415,7 +1415,7 @@ static void gen8_ggtt_insert_entries(struct i915_address_space *vm,
|
||||
(gen8_gtt_pte_t __iomem *)dev_priv->gtt.gsm + first_entry;
|
||||
int i = 0;
|
||||
struct sg_page_iter sg_iter;
|
||||
dma_addr_t addr = 0;
|
||||
dma_addr_t addr = 0; /* shut up gcc */
|
||||
|
||||
for_each_sg_page(st->sgl, &sg_iter, st->nents, 0) {
|
||||
addr = sg_dma_address(sg_iter.sg) +
|
||||
@ -1461,7 +1461,7 @@ static void gen6_ggtt_insert_entries(struct i915_address_space *vm,
|
||||
(gen6_gtt_pte_t __iomem *)dev_priv->gtt.gsm + first_entry;
|
||||
int i = 0;
|
||||
struct sg_page_iter sg_iter;
|
||||
dma_addr_t addr;
|
||||
dma_addr_t addr = 0;
|
||||
|
||||
for_each_sg_page(st->sgl, &sg_iter, st->nents, 0) {
|
||||
addr = sg_page_iter_dma_address(&sg_iter);
|
||||
@ -1475,9 +1475,10 @@ static void gen6_ggtt_insert_entries(struct i915_address_space *vm,
|
||||
* of NUMA access patterns. Therefore, even with the way we assume
|
||||
* hardware should work, we must keep this posting read for paranoia.
|
||||
*/
|
||||
if (i != 0)
|
||||
WARN_ON(readl(>t_entries[i-1]) !=
|
||||
vm->pte_encode(addr, level, true, flags));
|
||||
if (i != 0) {
|
||||
unsigned long gtt = readl(>t_entries[i-1]);
|
||||
WARN_ON(gtt != vm->pte_encode(addr, level, true, flags));
|
||||
}
|
||||
|
||||
/* This next bit makes the above posting read even more important. We
|
||||
* want to flush the TLBs only after we're certain all the PTE updates
|
||||
|
@ -229,6 +229,8 @@ static const char *hangcheck_action_to_str(enum intel_ring_hangcheck_action a)
|
||||
return "wait";
|
||||
case HANGCHECK_ACTIVE:
|
||||
return "active";
|
||||
case HANGCHECK_ACTIVE_LOOP:
|
||||
return "active (loop)";
|
||||
case HANGCHECK_KICK:
|
||||
return "kick";
|
||||
case HANGCHECK_HUNG:
|
||||
@ -359,6 +361,12 @@ int i915_error_state_to_str(struct drm_i915_error_state_buf *m,
|
||||
err_printf(m, "PCI ID: 0x%04x\n", dev->pdev->device);
|
||||
err_printf(m, "EIR: 0x%08x\n", error->eir);
|
||||
err_printf(m, "IER: 0x%08x\n", error->ier);
|
||||
if (INTEL_INFO(dev)->gen >= 8) {
|
||||
for (i = 0; i < 4; i++)
|
||||
err_printf(m, "GTIER gt %d: 0x%08x\n", i,
|
||||
error->gtier[i]);
|
||||
} else if (HAS_PCH_SPLIT(dev) || IS_VALLEYVIEW(dev))
|
||||
err_printf(m, "GTIER: 0x%08x\n", error->gtier[0]);
|
||||
err_printf(m, "PGTBL_ER: 0x%08x\n", error->pgtbl_er);
|
||||
err_printf(m, "FORCEWAKE: 0x%08x\n", error->forcewake);
|
||||
err_printf(m, "DERRMR: 0x%08x\n", error->derrmr);
|
||||
@ -784,7 +792,8 @@ static void gen8_record_semaphore_state(struct drm_i915_private *dev_priv,
|
||||
if (ring == to)
|
||||
continue;
|
||||
|
||||
signal_offset = (GEN8_SIGNAL_OFFSET(ring, i) & PAGE_MASK) / 4;
|
||||
signal_offset = (GEN8_SIGNAL_OFFSET(ring, i) & (PAGE_SIZE - 1))
|
||||
/ 4;
|
||||
tmp = error->semaphore_obj->pages[0];
|
||||
idx = intel_ring_sync_index(ring, to);
|
||||
|
||||
@ -1091,6 +1100,7 @@ static void i915_capture_reg_state(struct drm_i915_private *dev_priv,
|
||||
struct drm_i915_error_state *error)
|
||||
{
|
||||
struct drm_device *dev = dev_priv->dev;
|
||||
int i;
|
||||
|
||||
/* General organization
|
||||
* 1. Registers specific to a single generation
|
||||
@ -1102,7 +1112,8 @@ static void i915_capture_reg_state(struct drm_i915_private *dev_priv,
|
||||
|
||||
/* 1: Registers specific to a single generation */
|
||||
if (IS_VALLEYVIEW(dev)) {
|
||||
error->ier = I915_READ(GTIER) | I915_READ(VLV_IER);
|
||||
error->gtier[0] = I915_READ(GTIER);
|
||||
error->ier = I915_READ(VLV_IER);
|
||||
error->forcewake = I915_READ(FORCEWAKE_VLV);
|
||||
}
|
||||
|
||||
@ -1135,16 +1146,18 @@ static void i915_capture_reg_state(struct drm_i915_private *dev_priv,
|
||||
if (HAS_HW_CONTEXTS(dev))
|
||||
error->ccid = I915_READ(CCID);
|
||||
|
||||
if (HAS_PCH_SPLIT(dev))
|
||||
error->ier = I915_READ(DEIER) | I915_READ(GTIER);
|
||||
else {
|
||||
if (IS_GEN2(dev))
|
||||
error->ier = I915_READ16(IER);
|
||||
else
|
||||
error->ier = I915_READ(IER);
|
||||
if (INTEL_INFO(dev)->gen >= 8) {
|
||||
error->ier = I915_READ(GEN8_DE_MISC_IER);
|
||||
for (i = 0; i < 4; i++)
|
||||
error->gtier[i] = I915_READ(GEN8_GT_IER(i));
|
||||
} else if (HAS_PCH_SPLIT(dev)) {
|
||||
error->ier = I915_READ(DEIER);
|
||||
error->gtier[0] = I915_READ(GTIER);
|
||||
} else if (IS_GEN2(dev)) {
|
||||
error->ier = I915_READ16(IER);
|
||||
} else if (!IS_VALLEYVIEW(dev)) {
|
||||
error->ier = I915_READ(IER);
|
||||
}
|
||||
|
||||
/* 4: Everything else */
|
||||
error->eir = I915_READ(EIR);
|
||||
error->pgtbl_er = I915_READ(PGTBL_ER);
|
||||
|
||||
|
@ -3189,8 +3189,14 @@ ring_stuck(struct intel_engine_cs *ring, u64 acthd)
|
||||
struct drm_i915_private *dev_priv = dev->dev_private;
|
||||
u32 tmp;
|
||||
|
||||
if (ring->hangcheck.acthd != acthd)
|
||||
return HANGCHECK_ACTIVE;
|
||||
if (acthd != ring->hangcheck.acthd) {
|
||||
if (acthd > ring->hangcheck.max_acthd) {
|
||||
ring->hangcheck.max_acthd = acthd;
|
||||
return HANGCHECK_ACTIVE;
|
||||
}
|
||||
|
||||
return HANGCHECK_ACTIVE_LOOP;
|
||||
}
|
||||
|
||||
if (IS_GEN2(dev))
|
||||
return HANGCHECK_HUNG;
|
||||
@ -3301,8 +3307,9 @@ static void i915_hangcheck_elapsed(unsigned long data)
|
||||
switch (ring->hangcheck.action) {
|
||||
case HANGCHECK_IDLE:
|
||||
case HANGCHECK_WAIT:
|
||||
break;
|
||||
case HANGCHECK_ACTIVE:
|
||||
break;
|
||||
case HANGCHECK_ACTIVE_LOOP:
|
||||
ring->hangcheck.score += BUSY;
|
||||
break;
|
||||
case HANGCHECK_KICK:
|
||||
@ -3322,6 +3329,8 @@ static void i915_hangcheck_elapsed(unsigned long data)
|
||||
*/
|
||||
if (ring->hangcheck.score > 0)
|
||||
ring->hangcheck.score--;
|
||||
|
||||
ring->hangcheck.acthd = ring->hangcheck.max_acthd = 0;
|
||||
}
|
||||
|
||||
ring->hangcheck.seqno = seqno;
|
||||
|
@ -3863,47 +3863,47 @@ enum punit_power_well {
|
||||
|
||||
/* drain latency register values*/
|
||||
#define DRAIN_LATENCY_PRECISION_32 32
|
||||
#define DRAIN_LATENCY_PRECISION_16 16
|
||||
#define DRAIN_LATENCY_PRECISION_64 64
|
||||
#define VLV_DDL1 (VLV_DISPLAY_BASE + 0x70050)
|
||||
#define DDL_CURSORA_PRECISION_32 (1<<31)
|
||||
#define DDL_CURSORA_PRECISION_16 (0<<31)
|
||||
#define DDL_CURSORA_PRECISION_64 (1<<31)
|
||||
#define DDL_CURSORA_PRECISION_32 (0<<31)
|
||||
#define DDL_CURSORA_SHIFT 24
|
||||
#define DDL_SPRITEB_PRECISION_32 (1<<23)
|
||||
#define DDL_SPRITEB_PRECISION_16 (0<<23)
|
||||
#define DDL_SPRITEB_PRECISION_64 (1<<23)
|
||||
#define DDL_SPRITEB_PRECISION_32 (0<<23)
|
||||
#define DDL_SPRITEB_SHIFT 16
|
||||
#define DDL_SPRITEA_PRECISION_32 (1<<15)
|
||||
#define DDL_SPRITEA_PRECISION_16 (0<<15)
|
||||
#define DDL_SPRITEA_PRECISION_64 (1<<15)
|
||||
#define DDL_SPRITEA_PRECISION_32 (0<<15)
|
||||
#define DDL_SPRITEA_SHIFT 8
|
||||
#define DDL_PLANEA_PRECISION_32 (1<<7)
|
||||
#define DDL_PLANEA_PRECISION_16 (0<<7)
|
||||
#define DDL_PLANEA_PRECISION_64 (1<<7)
|
||||
#define DDL_PLANEA_PRECISION_32 (0<<7)
|
||||
#define DDL_PLANEA_SHIFT 0
|
||||
|
||||
#define VLV_DDL2 (VLV_DISPLAY_BASE + 0x70054)
|
||||
#define DDL_CURSORB_PRECISION_32 (1<<31)
|
||||
#define DDL_CURSORB_PRECISION_16 (0<<31)
|
||||
#define DDL_CURSORB_PRECISION_64 (1<<31)
|
||||
#define DDL_CURSORB_PRECISION_32 (0<<31)
|
||||
#define DDL_CURSORB_SHIFT 24
|
||||
#define DDL_SPRITED_PRECISION_32 (1<<23)
|
||||
#define DDL_SPRITED_PRECISION_16 (0<<23)
|
||||
#define DDL_SPRITED_PRECISION_64 (1<<23)
|
||||
#define DDL_SPRITED_PRECISION_32 (0<<23)
|
||||
#define DDL_SPRITED_SHIFT 16
|
||||
#define DDL_SPRITEC_PRECISION_32 (1<<15)
|
||||
#define DDL_SPRITEC_PRECISION_16 (0<<15)
|
||||
#define DDL_SPRITEC_PRECISION_64 (1<<15)
|
||||
#define DDL_SPRITEC_PRECISION_32 (0<<15)
|
||||
#define DDL_SPRITEC_SHIFT 8
|
||||
#define DDL_PLANEB_PRECISION_32 (1<<7)
|
||||
#define DDL_PLANEB_PRECISION_16 (0<<7)
|
||||
#define DDL_PLANEB_PRECISION_64 (1<<7)
|
||||
#define DDL_PLANEB_PRECISION_32 (0<<7)
|
||||
#define DDL_PLANEB_SHIFT 0
|
||||
|
||||
#define VLV_DDL3 (VLV_DISPLAY_BASE + 0x70058)
|
||||
#define DDL_CURSORC_PRECISION_32 (1<<31)
|
||||
#define DDL_CURSORC_PRECISION_16 (0<<31)
|
||||
#define DDL_CURSORC_PRECISION_64 (1<<31)
|
||||
#define DDL_CURSORC_PRECISION_32 (0<<31)
|
||||
#define DDL_CURSORC_SHIFT 24
|
||||
#define DDL_SPRITEF_PRECISION_32 (1<<23)
|
||||
#define DDL_SPRITEF_PRECISION_16 (0<<23)
|
||||
#define DDL_SPRITEF_PRECISION_64 (1<<23)
|
||||
#define DDL_SPRITEF_PRECISION_32 (0<<23)
|
||||
#define DDL_SPRITEF_SHIFT 16
|
||||
#define DDL_SPRITEE_PRECISION_32 (1<<15)
|
||||
#define DDL_SPRITEE_PRECISION_16 (0<<15)
|
||||
#define DDL_SPRITEE_PRECISION_64 (1<<15)
|
||||
#define DDL_SPRITEE_PRECISION_32 (0<<15)
|
||||
#define DDL_SPRITEE_SHIFT 8
|
||||
#define DDL_PLANEC_PRECISION_32 (1<<7)
|
||||
#define DDL_PLANEC_PRECISION_16 (0<<7)
|
||||
#define DDL_PLANEC_PRECISION_64 (1<<7)
|
||||
#define DDL_PLANEC_PRECISION_32 (0<<7)
|
||||
#define DDL_PLANEC_SHIFT 0
|
||||
|
||||
/* FIFO watermark sizes etc */
|
||||
|
@ -878,7 +878,7 @@ err:
|
||||
|
||||
/* error during parsing so set all pointers to null
|
||||
* because of partial parsing */
|
||||
memset(dev_priv->vbt.dsi.sequence, 0, MIPI_SEQ_MAX);
|
||||
memset(dev_priv->vbt.dsi.sequence, 0, sizeof(dev_priv->vbt.dsi.sequence));
|
||||
}
|
||||
|
||||
static void parse_ddi_port(struct drm_i915_private *dev_priv, enum port port,
|
||||
|
@ -6161,6 +6161,10 @@ static void vlv_crtc_clock_get(struct intel_crtc *crtc,
|
||||
u32 mdiv;
|
||||
int refclk = 100000;
|
||||
|
||||
/* In case of MIPI DPLL will not even be used */
|
||||
if (!(pipe_config->dpll_hw_state.dpll & DPLL_VCO_ENABLE))
|
||||
return;
|
||||
|
||||
mutex_lock(&dev_priv->dpio_lock);
|
||||
mdiv = vlv_dpio_read(dev_priv, pipe, VLV_PLL_DW3(pipe));
|
||||
mutex_unlock(&dev_priv->dpio_lock);
|
||||
|
@ -1285,6 +1285,19 @@ static void edp_panel_vdd_work(struct work_struct *__work)
|
||||
drm_modeset_unlock(&dev->mode_config.connection_mutex);
|
||||
}
|
||||
|
||||
static void edp_panel_vdd_schedule_off(struct intel_dp *intel_dp)
|
||||
{
|
||||
unsigned long delay;
|
||||
|
||||
/*
|
||||
* Queue the timer to fire a long time from now (relative to the power
|
||||
* down delay) to keep the panel power up across a sequence of
|
||||
* operations.
|
||||
*/
|
||||
delay = msecs_to_jiffies(intel_dp->panel_power_cycle_delay * 5);
|
||||
schedule_delayed_work(&intel_dp->panel_vdd_work, delay);
|
||||
}
|
||||
|
||||
static void edp_panel_vdd_off(struct intel_dp *intel_dp, bool sync)
|
||||
{
|
||||
if (!is_edp(intel_dp))
|
||||
@ -1294,17 +1307,10 @@ static void edp_panel_vdd_off(struct intel_dp *intel_dp, bool sync)
|
||||
|
||||
intel_dp->want_panel_vdd = false;
|
||||
|
||||
if (sync) {
|
||||
if (sync)
|
||||
edp_panel_vdd_off_sync(intel_dp);
|
||||
} else {
|
||||
/*
|
||||
* Queue the timer to fire a long
|
||||
* time from now (relative to the power down delay)
|
||||
* to keep the panel power up across a sequence of operations
|
||||
*/
|
||||
schedule_delayed_work(&intel_dp->panel_vdd_work,
|
||||
msecs_to_jiffies(intel_dp->panel_power_cycle_delay * 5));
|
||||
}
|
||||
else
|
||||
edp_panel_vdd_schedule_off(intel_dp);
|
||||
}
|
||||
|
||||
void intel_edp_panel_on(struct intel_dp *intel_dp)
|
||||
@ -1800,7 +1806,6 @@ static bool intel_edp_psr_match_conditions(struct intel_dp *intel_dp)
|
||||
struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
|
||||
|
||||
lockdep_assert_held(&dev_priv->psr.lock);
|
||||
lockdep_assert_held(&dev->struct_mutex);
|
||||
WARN_ON(!drm_modeset_is_locked(&dev->mode_config.connection_mutex));
|
||||
WARN_ON(!drm_modeset_is_locked(&crtc->mutex));
|
||||
|
||||
@ -3998,6 +4003,11 @@ void intel_dp_encoder_destroy(struct drm_encoder *encoder)
|
||||
kfree(intel_dig_port);
|
||||
}
|
||||
|
||||
static void intel_dp_encoder_reset(struct drm_encoder *encoder)
|
||||
{
|
||||
intel_edp_panel_vdd_sanitize(to_intel_encoder(encoder));
|
||||
}
|
||||
|
||||
static const struct drm_connector_funcs intel_dp_connector_funcs = {
|
||||
.dpms = intel_connector_dpms,
|
||||
.detect = intel_dp_detect,
|
||||
@ -4013,6 +4023,7 @@ static const struct drm_connector_helper_funcs intel_dp_connector_helper_funcs =
|
||||
};
|
||||
|
||||
static const struct drm_encoder_funcs intel_dp_enc_funcs = {
|
||||
.reset = intel_dp_encoder_reset,
|
||||
.destroy = intel_dp_encoder_destroy,
|
||||
};
|
||||
|
||||
@ -4445,6 +4456,32 @@ intel_dp_drrs_init(struct intel_digital_port *intel_dig_port,
|
||||
return downclock_mode;
|
||||
}
|
||||
|
||||
void intel_edp_panel_vdd_sanitize(struct intel_encoder *intel_encoder)
|
||||
{
|
||||
struct drm_device *dev = intel_encoder->base.dev;
|
||||
struct drm_i915_private *dev_priv = dev->dev_private;
|
||||
struct intel_dp *intel_dp;
|
||||
enum intel_display_power_domain power_domain;
|
||||
|
||||
if (intel_encoder->type != INTEL_OUTPUT_EDP)
|
||||
return;
|
||||
|
||||
intel_dp = enc_to_intel_dp(&intel_encoder->base);
|
||||
if (!edp_have_panel_vdd(intel_dp))
|
||||
return;
|
||||
/*
|
||||
* The VDD bit needs a power domain reference, so if the bit is
|
||||
* already enabled when we boot or resume, grab this reference and
|
||||
* schedule a vdd off, so we don't hold on to the reference
|
||||
* indefinitely.
|
||||
*/
|
||||
DRM_DEBUG_KMS("VDD left on by BIOS, adjusting state tracking\n");
|
||||
power_domain = intel_display_port_power_domain(intel_encoder);
|
||||
intel_display_power_get(dev_priv, power_domain);
|
||||
|
||||
edp_panel_vdd_schedule_off(intel_dp);
|
||||
}
|
||||
|
||||
static bool intel_edp_init_connector(struct intel_dp *intel_dp,
|
||||
struct intel_connector *intel_connector,
|
||||
struct edp_power_seq *power_seq)
|
||||
@ -4465,13 +4502,7 @@ static bool intel_edp_init_connector(struct intel_dp *intel_dp,
|
||||
if (!is_edp(intel_dp))
|
||||
return true;
|
||||
|
||||
/* The VDD bit needs a power domain reference, so if the bit is already
|
||||
* enabled when we boot, grab this reference. */
|
||||
if (edp_have_panel_vdd(intel_dp)) {
|
||||
enum intel_display_power_domain power_domain;
|
||||
power_domain = intel_display_port_power_domain(intel_encoder);
|
||||
intel_display_power_get(dev_priv, power_domain);
|
||||
}
|
||||
intel_edp_panel_vdd_sanitize(intel_encoder);
|
||||
|
||||
/* Cache DPCD and EDID for edp. */
|
||||
intel_edp_panel_vdd_on(intel_dp);
|
||||
|
@ -912,6 +912,7 @@ bool intel_dp_hpd_pulse(struct intel_digital_port *intel_dig_port,
|
||||
void intel_edp_backlight_on(struct intel_dp *intel_dp);
|
||||
void intel_edp_backlight_off(struct intel_dp *intel_dp);
|
||||
void intel_edp_panel_vdd_on(struct intel_dp *intel_dp);
|
||||
void intel_edp_panel_vdd_sanitize(struct intel_encoder *intel_encoder);
|
||||
void intel_edp_panel_on(struct intel_dp *intel_dp);
|
||||
void intel_edp_panel_off(struct intel_dp *intel_dp);
|
||||
void intel_edp_psr_enable(struct intel_dp *intel_dp);
|
||||
|
@ -92,6 +92,9 @@ static bool intel_dsi_compute_config(struct intel_encoder *encoder,
|
||||
if (fixed_mode)
|
||||
intel_fixed_panel_mode(fixed_mode, adjusted_mode);
|
||||
|
||||
/* DSI uses short packets for sync events, so clear mode flags for DSI */
|
||||
adjusted_mode->flags = 0;
|
||||
|
||||
if (intel_dsi->dev.dev_ops->mode_fixup)
|
||||
return intel_dsi->dev.dev_ops->mode_fixup(&intel_dsi->dev,
|
||||
mode, adjusted_mode);
|
||||
@ -152,6 +155,8 @@ static void intel_dsi_enable(struct intel_encoder *encoder)
|
||||
if (intel_dsi->dev.dev_ops->enable)
|
||||
intel_dsi->dev.dev_ops->enable(&intel_dsi->dev);
|
||||
|
||||
wait_for_dsi_fifo_empty(intel_dsi);
|
||||
|
||||
/* assert ip_tg_enable signal */
|
||||
temp = I915_READ(MIPI_PORT_CTRL(pipe)) & ~LANE_CONFIGURATION_MASK;
|
||||
temp = temp | intel_dsi->port_bits;
|
||||
@ -177,6 +182,10 @@ static void intel_dsi_pre_enable(struct intel_encoder *encoder)
|
||||
tmp |= DPLL_REFA_CLK_ENABLE_VLV;
|
||||
I915_WRITE(DPLL(pipe), tmp);
|
||||
|
||||
/* update the hw state for DPLL */
|
||||
intel_crtc->config.dpll_hw_state.dpll = DPLL_INTEGRATED_CLOCK_VLV |
|
||||
DPLL_REFA_CLK_ENABLE_VLV;
|
||||
|
||||
tmp = I915_READ(DSPCLK_GATE_D);
|
||||
tmp |= DPOUNIT_CLOCK_GATE_DISABLE;
|
||||
I915_WRITE(DSPCLK_GATE_D, tmp);
|
||||
@ -192,6 +201,8 @@ static void intel_dsi_pre_enable(struct intel_encoder *encoder)
|
||||
if (intel_dsi->dev.dev_ops->send_otp_cmds)
|
||||
intel_dsi->dev.dev_ops->send_otp_cmds(&intel_dsi->dev);
|
||||
|
||||
wait_for_dsi_fifo_empty(intel_dsi);
|
||||
|
||||
/* Enable port in pre-enable phase itself because as per hw team
|
||||
* recommendation, port should be enabled befor plane & pipe */
|
||||
intel_dsi_enable(encoder);
|
||||
@ -232,6 +243,8 @@ static void intel_dsi_disable(struct intel_encoder *encoder)
|
||||
DRM_DEBUG_KMS("\n");
|
||||
|
||||
if (is_vid_mode(intel_dsi)) {
|
||||
wait_for_dsi_fifo_empty(intel_dsi);
|
||||
|
||||
/* de-assert ip_tg_enable signal */
|
||||
temp = I915_READ(MIPI_PORT_CTRL(pipe));
|
||||
I915_WRITE(MIPI_PORT_CTRL(pipe), temp & ~DPI_ENABLE);
|
||||
@ -261,6 +274,8 @@ static void intel_dsi_disable(struct intel_encoder *encoder)
|
||||
* some next enable sequence send turn on packet error is observed */
|
||||
if (intel_dsi->dev.dev_ops->disable)
|
||||
intel_dsi->dev.dev_ops->disable(&intel_dsi->dev);
|
||||
|
||||
wait_for_dsi_fifo_empty(intel_dsi);
|
||||
}
|
||||
|
||||
static void intel_dsi_clear_device_ready(struct intel_encoder *encoder)
|
||||
@ -351,9 +366,21 @@ static bool intel_dsi_get_hw_state(struct intel_encoder *encoder,
|
||||
static void intel_dsi_get_config(struct intel_encoder *encoder,
|
||||
struct intel_crtc_config *pipe_config)
|
||||
{
|
||||
u32 pclk;
|
||||
DRM_DEBUG_KMS("\n");
|
||||
|
||||
/* XXX: read flags, set to adjusted_mode */
|
||||
/*
|
||||
* DPLL_MD is not used in case of DSI, reading will get some default value
|
||||
* set dpll_md = 0
|
||||
*/
|
||||
pipe_config->dpll_hw_state.dpll_md = 0;
|
||||
|
||||
pclk = vlv_get_dsi_pclk(encoder, pipe_config->pipe_bpp);
|
||||
if (!pclk)
|
||||
return;
|
||||
|
||||
pipe_config->adjusted_mode.crtc_clock = pclk;
|
||||
pipe_config->port_clock = pclk;
|
||||
}
|
||||
|
||||
static enum drm_mode_status
|
||||
|
@ -132,6 +132,7 @@ static inline struct intel_dsi *enc_to_intel_dsi(struct drm_encoder *encoder)
|
||||
|
||||
extern void vlv_enable_dsi_pll(struct intel_encoder *encoder);
|
||||
extern void vlv_disable_dsi_pll(struct intel_encoder *encoder);
|
||||
extern u32 vlv_get_dsi_pclk(struct intel_encoder *encoder, int pipe_bpp);
|
||||
|
||||
extern struct intel_dsi_dev_ops vbt_generic_dsi_display_ops;
|
||||
|
||||
|
@ -419,3 +419,19 @@ int dpi_send_cmd(struct intel_dsi *intel_dsi, u32 cmd, bool hs)
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void wait_for_dsi_fifo_empty(struct intel_dsi *intel_dsi)
|
||||
{
|
||||
struct drm_encoder *encoder = &intel_dsi->base.base;
|
||||
struct drm_device *dev = encoder->dev;
|
||||
struct drm_i915_private *dev_priv = dev->dev_private;
|
||||
struct intel_crtc *intel_crtc = to_intel_crtc(encoder->crtc);
|
||||
enum pipe pipe = intel_crtc->pipe;
|
||||
u32 mask;
|
||||
|
||||
mask = LP_CTRL_FIFO_EMPTY | HS_CTRL_FIFO_EMPTY |
|
||||
LP_DATA_FIFO_EMPTY | HS_DATA_FIFO_EMPTY;
|
||||
|
||||
if (wait_for((I915_READ(MIPI_GEN_FIFO_STAT(pipe)) & mask) == mask, 100))
|
||||
DRM_ERROR("DPI FIFOs are not empty\n");
|
||||
}
|
||||
|
@ -51,6 +51,7 @@ int dsi_vc_generic_read(struct intel_dsi *intel_dsi, int channel,
|
||||
u8 *reqdata, int reqlen, u8 *buf, int buflen);
|
||||
|
||||
int dpi_send_cmd(struct intel_dsi *intel_dsi, u32 cmd, bool hs);
|
||||
void wait_for_dsi_fifo_empty(struct intel_dsi *intel_dsi);
|
||||
|
||||
/* XXX: questionable write helpers */
|
||||
static inline int dsi_vc_dcs_write_0(struct intel_dsi *intel_dsi,
|
||||
|
@ -298,3 +298,84 @@ void vlv_disable_dsi_pll(struct intel_encoder *encoder)
|
||||
|
||||
mutex_unlock(&dev_priv->dpio_lock);
|
||||
}
|
||||
|
||||
static void assert_bpp_mismatch(int pixel_format, int pipe_bpp)
|
||||
{
|
||||
int bpp;
|
||||
|
||||
switch (pixel_format) {
|
||||
default:
|
||||
case VID_MODE_FORMAT_RGB888:
|
||||
case VID_MODE_FORMAT_RGB666_LOOSE:
|
||||
bpp = 24;
|
||||
break;
|
||||
case VID_MODE_FORMAT_RGB666:
|
||||
bpp = 18;
|
||||
break;
|
||||
case VID_MODE_FORMAT_RGB565:
|
||||
bpp = 16;
|
||||
break;
|
||||
}
|
||||
|
||||
WARN(bpp != pipe_bpp,
|
||||
"bpp match assertion failure (expected %d, current %d)\n",
|
||||
bpp, pipe_bpp);
|
||||
}
|
||||
|
||||
u32 vlv_get_dsi_pclk(struct intel_encoder *encoder, int pipe_bpp)
|
||||
{
|
||||
struct drm_i915_private *dev_priv = encoder->base.dev->dev_private;
|
||||
struct intel_dsi *intel_dsi = enc_to_intel_dsi(&encoder->base);
|
||||
u32 dsi_clock, pclk;
|
||||
u32 pll_ctl, pll_div;
|
||||
u32 m = 0, p = 0;
|
||||
int refclk = 25000;
|
||||
int i;
|
||||
|
||||
DRM_DEBUG_KMS("\n");
|
||||
|
||||
mutex_lock(&dev_priv->dpio_lock);
|
||||
pll_ctl = vlv_cck_read(dev_priv, CCK_REG_DSI_PLL_CONTROL);
|
||||
pll_div = vlv_cck_read(dev_priv, CCK_REG_DSI_PLL_DIVIDER);
|
||||
mutex_unlock(&dev_priv->dpio_lock);
|
||||
|
||||
/* mask out other bits and extract the P1 divisor */
|
||||
pll_ctl &= DSI_PLL_P1_POST_DIV_MASK;
|
||||
pll_ctl = pll_ctl >> (DSI_PLL_P1_POST_DIV_SHIFT - 2);
|
||||
|
||||
/* mask out the other bits and extract the M1 divisor */
|
||||
pll_div &= DSI_PLL_M1_DIV_MASK;
|
||||
pll_div = pll_div >> DSI_PLL_M1_DIV_SHIFT;
|
||||
|
||||
while (pll_ctl) {
|
||||
pll_ctl = pll_ctl >> 1;
|
||||
p++;
|
||||
}
|
||||
p--;
|
||||
|
||||
if (!p) {
|
||||
DRM_ERROR("wrong P1 divisor\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(lfsr_converts); i++) {
|
||||
if (lfsr_converts[i] == pll_div)
|
||||
break;
|
||||
}
|
||||
|
||||
if (i == ARRAY_SIZE(lfsr_converts)) {
|
||||
DRM_ERROR("wrong m_seed programmed\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
m = i + 62;
|
||||
|
||||
dsi_clock = (m * refclk) / p;
|
||||
|
||||
/* pixel_format and pipe_bpp should agree */
|
||||
assert_bpp_mismatch(intel_dsi->pixel_format, pipe_bpp);
|
||||
|
||||
pclk = DIV_ROUND_CLOSEST(dsi_clock * intel_dsi->lane_count, pipe_bpp);
|
||||
|
||||
return pclk;
|
||||
}
|
||||
|
@ -1287,15 +1287,14 @@ static bool vlv_compute_drain_latency(struct drm_device *dev,
|
||||
pixel_size = crtc->primary->fb->bits_per_pixel / 8; /* BPP */
|
||||
|
||||
entries = (clock / 1000) * pixel_size;
|
||||
*plane_prec_mult = (entries > 256) ?
|
||||
DRAIN_LATENCY_PRECISION_32 : DRAIN_LATENCY_PRECISION_16;
|
||||
*plane_dl = (64 * (*plane_prec_mult) * 4) / ((clock / 1000) *
|
||||
pixel_size);
|
||||
*plane_prec_mult = (entries > 128) ?
|
||||
DRAIN_LATENCY_PRECISION_64 : DRAIN_LATENCY_PRECISION_32;
|
||||
*plane_dl = (64 * (*plane_prec_mult) * 4) / entries;
|
||||
|
||||
entries = (clock / 1000) * 4; /* BPP is always 4 for cursor */
|
||||
*cursor_prec_mult = (entries > 256) ?
|
||||
DRAIN_LATENCY_PRECISION_32 : DRAIN_LATENCY_PRECISION_16;
|
||||
*cursor_dl = (64 * (*cursor_prec_mult) * 4) / ((clock / 1000) * 4);
|
||||
*cursor_prec_mult = (entries > 128) ?
|
||||
DRAIN_LATENCY_PRECISION_64 : DRAIN_LATENCY_PRECISION_32;
|
||||
*cursor_dl = (64 * (*cursor_prec_mult) * 4) / entries;
|
||||
|
||||
return true;
|
||||
}
|
||||
@ -1320,9 +1319,9 @@ static void vlv_update_drain_latency(struct drm_device *dev)
|
||||
if (vlv_compute_drain_latency(dev, 0, &plane_prec_mult, &planea_dl,
|
||||
&cursor_prec_mult, &cursora_dl)) {
|
||||
cursora_prec = (cursor_prec_mult == DRAIN_LATENCY_PRECISION_32) ?
|
||||
DDL_CURSORA_PRECISION_32 : DDL_CURSORA_PRECISION_16;
|
||||
DDL_CURSORA_PRECISION_32 : DDL_CURSORA_PRECISION_64;
|
||||
planea_prec = (plane_prec_mult == DRAIN_LATENCY_PRECISION_32) ?
|
||||
DDL_PLANEA_PRECISION_32 : DDL_PLANEA_PRECISION_16;
|
||||
DDL_PLANEA_PRECISION_32 : DDL_PLANEA_PRECISION_64;
|
||||
|
||||
I915_WRITE(VLV_DDL1, cursora_prec |
|
||||
(cursora_dl << DDL_CURSORA_SHIFT) |
|
||||
@ -1333,9 +1332,9 @@ static void vlv_update_drain_latency(struct drm_device *dev)
|
||||
if (vlv_compute_drain_latency(dev, 1, &plane_prec_mult, &planeb_dl,
|
||||
&cursor_prec_mult, &cursorb_dl)) {
|
||||
cursorb_prec = (cursor_prec_mult == DRAIN_LATENCY_PRECISION_32) ?
|
||||
DDL_CURSORB_PRECISION_32 : DDL_CURSORB_PRECISION_16;
|
||||
DDL_CURSORB_PRECISION_32 : DDL_CURSORB_PRECISION_64;
|
||||
planeb_prec = (plane_prec_mult == DRAIN_LATENCY_PRECISION_32) ?
|
||||
DDL_PLANEB_PRECISION_32 : DDL_PLANEB_PRECISION_16;
|
||||
DDL_PLANEB_PRECISION_32 : DDL_PLANEB_PRECISION_64;
|
||||
|
||||
I915_WRITE(VLV_DDL2, cursorb_prec |
|
||||
(cursorb_dl << DDL_CURSORB_SHIFT) |
|
||||
@ -3420,10 +3419,10 @@ static void intel_print_rc6_info(struct drm_device *dev, u32 mode)
|
||||
else
|
||||
mode = 0;
|
||||
}
|
||||
DRM_INFO("Enabling RC6 states: RC6 %s, RC6p %s, RC6pp %s\n",
|
||||
(mode & GEN6_RC_CTL_RC6_ENABLE) ? "on" : "off",
|
||||
(mode & GEN6_RC_CTL_RC6p_ENABLE) ? "on" : "off",
|
||||
(mode & GEN6_RC_CTL_RC6pp_ENABLE) ? "on" : "off");
|
||||
DRM_DEBUG_KMS("Enabling RC6 states: RC6 %s, RC6p %s, RC6pp %s\n",
|
||||
(mode & GEN6_RC_CTL_RC6_ENABLE) ? "on" : "off",
|
||||
(mode & GEN6_RC_CTL_RC6p_ENABLE) ? "on" : "off",
|
||||
(mode & GEN6_RC_CTL_RC6pp_ENABLE) ? "on" : "off");
|
||||
}
|
||||
|
||||
static int sanitize_rc6_option(const struct drm_device *dev, int enable_rc6)
|
||||
@ -3447,8 +3446,8 @@ static int sanitize_rc6_option(const struct drm_device *dev, int enable_rc6)
|
||||
mask = INTEL_RC6_ENABLE;
|
||||
|
||||
if ((enable_rc6 & mask) != enable_rc6)
|
||||
DRM_INFO("Adjusting RC6 mask to %d (requested %d, valid %d)\n",
|
||||
enable_rc6 & mask, enable_rc6, mask);
|
||||
DRM_DEBUG_KMS("Adjusting RC6 mask to %d (requested %d, valid %d)\n",
|
||||
enable_rc6 & mask, enable_rc6, mask);
|
||||
|
||||
return enable_rc6 & mask;
|
||||
}
|
||||
@ -5228,11 +5227,9 @@ static void gen6_check_mch_setup(struct drm_device *dev)
|
||||
uint32_t tmp;
|
||||
|
||||
tmp = I915_READ(MCH_SSKPD);
|
||||
if ((tmp & MCH_SSKPD_WM0_MASK) != MCH_SSKPD_WM0_VAL) {
|
||||
DRM_INFO("Wrong MCH_SSKPD value: 0x%08x\n", tmp);
|
||||
DRM_INFO("This can cause pipe underruns and display issues.\n");
|
||||
DRM_INFO("Please upgrade your BIOS to fix this.\n");
|
||||
}
|
||||
if ((tmp & MCH_SSKPD_WM0_MASK) != MCH_SSKPD_WM0_VAL)
|
||||
DRM_DEBUG_KMS("Wrong MCH_SSKPD value: 0x%08x This can cause underruns.\n",
|
||||
tmp);
|
||||
}
|
||||
|
||||
static void gen6_init_clock_gating(struct drm_device *dev)
|
||||
|
@ -379,6 +379,27 @@ gen7_render_ring_flush(struct intel_engine_cs *ring,
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
gen8_emit_pipe_control(struct intel_engine_cs *ring,
|
||||
u32 flags, u32 scratch_addr)
|
||||
{
|
||||
int ret;
|
||||
|
||||
ret = intel_ring_begin(ring, 6);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
intel_ring_emit(ring, GFX_OP_PIPE_CONTROL(6));
|
||||
intel_ring_emit(ring, flags);
|
||||
intel_ring_emit(ring, scratch_addr);
|
||||
intel_ring_emit(ring, 0);
|
||||
intel_ring_emit(ring, 0);
|
||||
intel_ring_emit(ring, 0);
|
||||
intel_ring_advance(ring);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
gen8_render_ring_flush(struct intel_engine_cs *ring,
|
||||
u32 invalidate_domains, u32 flush_domains)
|
||||
@ -402,22 +423,17 @@ gen8_render_ring_flush(struct intel_engine_cs *ring,
|
||||
flags |= PIPE_CONTROL_STATE_CACHE_INVALIDATE;
|
||||
flags |= PIPE_CONTROL_QW_WRITE;
|
||||
flags |= PIPE_CONTROL_GLOBAL_GTT_IVB;
|
||||
|
||||
/* WaCsStallBeforeStateCacheInvalidate:bdw,chv */
|
||||
ret = gen8_emit_pipe_control(ring,
|
||||
PIPE_CONTROL_CS_STALL |
|
||||
PIPE_CONTROL_STALL_AT_SCOREBOARD,
|
||||
0);
|
||||
if (ret)
|
||||
return ret;
|
||||
}
|
||||
|
||||
ret = intel_ring_begin(ring, 6);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
intel_ring_emit(ring, GFX_OP_PIPE_CONTROL(6));
|
||||
intel_ring_emit(ring, flags);
|
||||
intel_ring_emit(ring, scratch_addr);
|
||||
intel_ring_emit(ring, 0);
|
||||
intel_ring_emit(ring, 0);
|
||||
intel_ring_emit(ring, 0);
|
||||
intel_ring_advance(ring);
|
||||
|
||||
return 0;
|
||||
|
||||
return gen8_emit_pipe_control(ring, flags, scratch_addr);
|
||||
}
|
||||
|
||||
static void ring_write_tail(struct intel_engine_cs *ring,
|
||||
@ -516,6 +532,9 @@ static int init_ring_common(struct intel_engine_cs *ring)
|
||||
else
|
||||
ring_setup_phys_status_page(ring);
|
||||
|
||||
/* Enforce ordering by reading HEAD register back */
|
||||
I915_READ_HEAD(ring);
|
||||
|
||||
/* Initialize the ring. This must happen _after_ we've cleared the ring
|
||||
* registers with the above sequence (the readback of the HEAD registers
|
||||
* also enforces ordering), otherwise the hw might lose the new ring
|
||||
|
@ -70,6 +70,7 @@ enum intel_ring_hangcheck_action {
|
||||
HANGCHECK_IDLE = 0,
|
||||
HANGCHECK_WAIT,
|
||||
HANGCHECK_ACTIVE,
|
||||
HANGCHECK_ACTIVE_LOOP,
|
||||
HANGCHECK_KICK,
|
||||
HANGCHECK_HUNG,
|
||||
};
|
||||
@ -78,6 +79,7 @@ enum intel_ring_hangcheck_action {
|
||||
|
||||
struct intel_ring_hangcheck {
|
||||
u64 acthd;
|
||||
u64 max_acthd;
|
||||
u32 seqno;
|
||||
int score;
|
||||
enum intel_ring_hangcheck_action action;
|
||||
|
Loading…
Reference in New Issue
Block a user