Merge branch 'drm-intel-fixes' of git://people.freedesktop.org/~danvet/drm-intel into drm-next
Daniel writes: As promised a stash of (mostly) fixes. Two pieces of non-fixes included: - A notch more gtt refactoring from Ben, beating to death with igt in our nightly testing. - Support for display display-less server chips (again from Ben). New hw support which is only likely to break itself ;-) Otherwise just tons of fixes: - hpd irq storm mitigation from Egbert Eich. Your -next tree already has the infrastructure, this here just supplies the logic. - sdvo hw state check fix from Egbert Eich - fb cb tune settings for the pch pll clocks on cpt/ppt - "Bring a bigger gun" coherence workaround for multi-threade, mulit-core & thrashing tiled gtt cpu access from Chris. - Update haswell mPHY code. - l3$ caching for context objects on ivb/hsw (Chris). - dp aux refclock fix for haswell (Jani) - moar overclocking fixes for snb/ivb (Ben) - ecobits ppgtt pte caching control fixes from Ville - fence stride check fixes and limit improvements (Ville) - fix up crtc force restoring, potentially resulting in tons of hw state check WARNs - OOPS fix for NULL derefencing of fb pointers when force-restoring a crtc when other crtcs are disabled and the force-restored crtc is _not_ the first one. - Fix pfit disabling on gen2/3. - Haswell ring freq scaling fixes (Chris). - backlight init/teardown fix (failed eDP init killed the lvds backlight) from Jani - cpt/ppt fdi polarity fixes from Paulo (should help a lot of the FDI link train failures). - And a bunch of smaller things all over. * 'drm-intel-fixes' of git://people.freedesktop.org/~danvet/drm-intel: (56 commits) drm/i915: fix bpc vs. bpp confusion in intel_crtc_compute_config drm/i915: move cpu_transcoder to the pipe configuration drm/i915: preserve the PBC bits of TRANS_CHICKEN2 drm/i915: set CPT FDI RX polarity bits based on VBT drm/i915: Add Reenable Timer to turn Hotplug Detection back on (v4) drm/i915: Disable HPD interrupt on pin when irq storm is detected (v3) drm/i915: Mask out the HPD irq bits before setting them individually. drm/i915: (re)init HPD interrupt storm statistics drm/i915: Add HPD IRQ storm detection (v5) drm/i915: WARN when LPT-LP is not paired with ULT CPU drm/i915: don't intel_crt_init on any ULT machines drm/i915: remove comment about IVB link training from intel_pm.c drm/i915: VLV doesn't have LLC drm/i915: Scale ring, rather than ia, frequency on Haswell drm/i915: shorten debugfs output simple attributes drm/i915: Fixup pfit disabling for gen2/3 drm/i915: Fixup Oops in the pipe config computation drm/i915: ensure single initialization and cleanup of backlight device drm/i915: don't touch the PF regs if the power well is down drm/i915: add intel_using_power_well ...
This commit is contained in:
commit
f0aa848fe5
|
@ -901,7 +901,7 @@ i915_next_seqno_set(void *data, u64 val)
|
|||
|
||||
DEFINE_SIMPLE_ATTRIBUTE(i915_next_seqno_fops,
|
||||
i915_next_seqno_get, i915_next_seqno_set,
|
||||
"next_seqno : 0x%llx\n");
|
||||
"0x%llx\n");
|
||||
|
||||
static int i915_rstdby_delays(struct seq_file *m, void *unused)
|
||||
{
|
||||
|
@ -1006,6 +1006,9 @@ static int i915_cur_delayinfo(struct seq_file *m, void *unused)
|
|||
max_freq = rp_state_cap & 0xff;
|
||||
seq_printf(m, "Max non-overclocked (RP0) frequency: %dMHz\n",
|
||||
max_freq * GT_FREQUENCY_MULTIPLIER);
|
||||
|
||||
seq_printf(m, "Max overclocked frequency: %dMHz\n",
|
||||
dev_priv->rps.hw_max * GT_FREQUENCY_MULTIPLIER);
|
||||
} else {
|
||||
seq_printf(m, "no P-state info available\n");
|
||||
}
|
||||
|
@ -1354,7 +1357,7 @@ static int i915_ring_freq_table(struct seq_file *m, void *unused)
|
|||
if (ret)
|
||||
return ret;
|
||||
|
||||
seq_printf(m, "GPU freq (MHz)\tEffective CPU freq (MHz)\n");
|
||||
seq_printf(m, "GPU freq (MHz)\tEffective CPU freq (MHz)\tEffective Ring freq (MHz)\n");
|
||||
|
||||
for (gpu_freq = dev_priv->rps.min_delay;
|
||||
gpu_freq <= dev_priv->rps.max_delay;
|
||||
|
@ -1363,7 +1366,10 @@ static int i915_ring_freq_table(struct seq_file *m, void *unused)
|
|||
sandybridge_pcode_read(dev_priv,
|
||||
GEN6_PCODE_READ_MIN_FREQ_TABLE,
|
||||
&ia_freq);
|
||||
seq_printf(m, "%d\t\t%d\n", gpu_freq * GT_FREQUENCY_MULTIPLIER, ia_freq * 100);
|
||||
seq_printf(m, "%d\t\t%d\t\t\t\t%d\n",
|
||||
gpu_freq * GT_FREQUENCY_MULTIPLIER,
|
||||
((ia_freq >> 0) & 0xff) * 100,
|
||||
((ia_freq >> 8) & 0xff) * 100);
|
||||
}
|
||||
|
||||
mutex_unlock(&dev_priv->rps.hw_lock);
|
||||
|
@ -1687,7 +1693,7 @@ i915_wedged_set(void *data, u64 val)
|
|||
|
||||
DEFINE_SIMPLE_ATTRIBUTE(i915_wedged_fops,
|
||||
i915_wedged_get, i915_wedged_set,
|
||||
"wedged : %llu\n");
|
||||
"%llu\n");
|
||||
|
||||
static int
|
||||
i915_ring_stop_get(void *data, u64 *val)
|
||||
|
@ -1841,7 +1847,7 @@ i915_max_freq_set(void *data, u64 val)
|
|||
|
||||
DEFINE_SIMPLE_ATTRIBUTE(i915_max_freq_fops,
|
||||
i915_max_freq_get, i915_max_freq_set,
|
||||
"max freq: %llu\n");
|
||||
"%llu\n");
|
||||
|
||||
static int
|
||||
i915_min_freq_get(void *data, u64 *val)
|
||||
|
@ -1892,7 +1898,7 @@ i915_min_freq_set(void *data, u64 val)
|
|||
|
||||
DEFINE_SIMPLE_ATTRIBUTE(i915_min_freq_fops,
|
||||
i915_min_freq_get, i915_min_freq_set,
|
||||
"min freq: %llu\n");
|
||||
"%llu\n");
|
||||
|
||||
static int
|
||||
i915_cache_sharing_get(void *data, u64 *val)
|
||||
|
|
|
@ -1322,6 +1322,10 @@ static int i915_load_modeset_init(struct drm_device *dev)
|
|||
/* Always safe in the mode setting case. */
|
||||
/* FIXME: do pre/post-mode set stuff in core KMS code */
|
||||
dev->vblank_disable_allowed = 1;
|
||||
if (INTEL_INFO(dev)->num_pipes == 0) {
|
||||
dev_priv->mm.suspended = 0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
ret = intel_fbdev_init(dev);
|
||||
if (ret)
|
||||
|
@ -1514,6 +1518,28 @@ int i915_driver_load(struct drm_device *dev, unsigned long flags)
|
|||
goto free_priv;
|
||||
}
|
||||
|
||||
mmio_bar = IS_GEN2(dev) ? 1 : 0;
|
||||
/* Before gen4, the registers and the GTT are behind different BARs.
|
||||
* However, from gen4 onwards, the registers and the GTT are shared
|
||||
* in the same BAR, so we want to restrict this ioremap from
|
||||
* clobbering the GTT which we want ioremap_wc instead. Fortunately,
|
||||
* the register BAR remains the same size for all the earlier
|
||||
* generations up to Ironlake.
|
||||
*/
|
||||
if (info->gen < 5)
|
||||
mmio_size = 512*1024;
|
||||
else
|
||||
mmio_size = 2*1024*1024;
|
||||
|
||||
dev_priv->regs = pci_iomap(dev->pdev, mmio_bar, mmio_size);
|
||||
if (!dev_priv->regs) {
|
||||
DRM_ERROR("failed to map registers\n");
|
||||
ret = -EIO;
|
||||
goto put_bridge;
|
||||
}
|
||||
|
||||
intel_early_sanitize_regs(dev);
|
||||
|
||||
ret = i915_gem_gtt_init(dev);
|
||||
if (ret)
|
||||
goto put_bridge;
|
||||
|
@ -1538,28 +1564,6 @@ int i915_driver_load(struct drm_device *dev, unsigned long flags)
|
|||
if (IS_BROADWATER(dev) || IS_CRESTLINE(dev))
|
||||
dma_set_coherent_mask(&dev->pdev->dev, DMA_BIT_MASK(32));
|
||||
|
||||
mmio_bar = IS_GEN2(dev) ? 1 : 0;
|
||||
/* Before gen4, the registers and the GTT are behind different BARs.
|
||||
* However, from gen4 onwards, the registers and the GTT are shared
|
||||
* in the same BAR, so we want to restrict this ioremap from
|
||||
* clobbering the GTT which we want ioremap_wc instead. Fortunately,
|
||||
* the register BAR remains the same size for all the earlier
|
||||
* generations up to Ironlake.
|
||||
*/
|
||||
if (info->gen < 5)
|
||||
mmio_size = 512*1024;
|
||||
else
|
||||
mmio_size = 2*1024*1024;
|
||||
|
||||
dev_priv->regs = pci_iomap(dev->pdev, mmio_bar, mmio_size);
|
||||
if (!dev_priv->regs) {
|
||||
DRM_ERROR("failed to map registers\n");
|
||||
ret = -EIO;
|
||||
goto put_gmch;
|
||||
}
|
||||
|
||||
intel_early_sanitize_regs(dev);
|
||||
|
||||
aperture_size = dev_priv->gtt.mappable_end;
|
||||
|
||||
dev_priv->gtt.mappable =
|
||||
|
@ -1634,9 +1638,11 @@ int i915_driver_load(struct drm_device *dev, unsigned long flags)
|
|||
if (IS_VALLEYVIEW(dev))
|
||||
dev_priv->num_plane = 2;
|
||||
|
||||
ret = drm_vblank_init(dev, INTEL_INFO(dev)->num_pipes);
|
||||
if (ret)
|
||||
goto out_gem_unload;
|
||||
if (INTEL_INFO(dev)->num_pipes) {
|
||||
ret = drm_vblank_init(dev, INTEL_INFO(dev)->num_pipes);
|
||||
if (ret)
|
||||
goto out_gem_unload;
|
||||
}
|
||||
|
||||
/* Start out suspended */
|
||||
dev_priv->mm.suspended = 1;
|
||||
|
@ -1651,9 +1657,11 @@ int i915_driver_load(struct drm_device *dev, unsigned long flags)
|
|||
|
||||
i915_setup_sysfs(dev);
|
||||
|
||||
/* Must be done after probing outputs */
|
||||
intel_opregion_init(dev);
|
||||
acpi_video_register();
|
||||
if (INTEL_INFO(dev)->num_pipes) {
|
||||
/* Must be done after probing outputs */
|
||||
intel_opregion_init(dev);
|
||||
acpi_video_register();
|
||||
}
|
||||
|
||||
if (IS_GEN5(dev))
|
||||
intel_gpu_ips_init(dev_priv);
|
||||
|
@ -1678,10 +1686,9 @@ out_mtrrfree:
|
|||
dev_priv->mm.gtt_mtrr = -1;
|
||||
}
|
||||
io_mapping_free(dev_priv->gtt.mappable);
|
||||
dev_priv->gtt.gtt_remove(dev);
|
||||
out_rmmap:
|
||||
pci_iounmap(dev->pdev, dev_priv->regs);
|
||||
put_gmch:
|
||||
dev_priv->gtt.gtt_remove(dev);
|
||||
put_bridge:
|
||||
pci_dev_put(dev_priv->bridge_dev);
|
||||
free_priv:
|
||||
|
|
|
@ -140,6 +140,16 @@ extern int intel_agp_enabled;
|
|||
.subdevice = PCI_ANY_ID, \
|
||||
.driver_data = (unsigned long) info }
|
||||
|
||||
#define INTEL_QUANTA_VGA_DEVICE(info) { \
|
||||
.class = PCI_BASE_CLASS_DISPLAY << 16, \
|
||||
.class_mask = 0xff0000, \
|
||||
.vendor = 0x8086, \
|
||||
.device = 0x16a, \
|
||||
.subvendor = 0x152d, \
|
||||
.subdevice = 0x8990, \
|
||||
.driver_data = (unsigned long) info }
|
||||
|
||||
|
||||
static const struct intel_device_info intel_i830_info = {
|
||||
.gen = 2, .is_mobile = 1, .cursor_needs_physical = 1, .num_pipes = 2,
|
||||
.has_overlay = 1, .overlay_needs_physical = 1,
|
||||
|
@ -272,12 +282,19 @@ static const struct intel_device_info intel_ivybridge_m_info = {
|
|||
.is_mobile = 1,
|
||||
};
|
||||
|
||||
static const struct intel_device_info intel_ivybridge_q_info = {
|
||||
GEN7_FEATURES,
|
||||
.is_ivybridge = 1,
|
||||
.num_pipes = 0, /* legal, last one wins */
|
||||
};
|
||||
|
||||
static const struct intel_device_info intel_valleyview_m_info = {
|
||||
GEN7_FEATURES,
|
||||
.is_mobile = 1,
|
||||
.num_pipes = 2,
|
||||
.is_valleyview = 1,
|
||||
.display_mmio_offset = VLV_DISPLAY_BASE,
|
||||
.has_llc = 0, /* legal, last one wins */
|
||||
};
|
||||
|
||||
static const struct intel_device_info intel_valleyview_d_info = {
|
||||
|
@ -285,6 +302,7 @@ static const struct intel_device_info intel_valleyview_d_info = {
|
|||
.num_pipes = 2,
|
||||
.is_valleyview = 1,
|
||||
.display_mmio_offset = VLV_DISPLAY_BASE,
|
||||
.has_llc = 0, /* legal, last one wins */
|
||||
};
|
||||
|
||||
static const struct intel_device_info intel_haswell_d_info = {
|
||||
|
@ -342,6 +360,7 @@ static const struct pci_device_id pciidlist[] = { /* aka */
|
|||
INTEL_VGA_DEVICE(0x0152, &intel_ivybridge_d_info), /* GT1 desktop */
|
||||
INTEL_VGA_DEVICE(0x0162, &intel_ivybridge_d_info), /* GT2 desktop */
|
||||
INTEL_VGA_DEVICE(0x015a, &intel_ivybridge_d_info), /* GT1 server */
|
||||
INTEL_QUANTA_VGA_DEVICE(&intel_ivybridge_q_info), /* Quanta transcode */
|
||||
INTEL_VGA_DEVICE(0x016a, &intel_ivybridge_d_info), /* GT2 server */
|
||||
INTEL_VGA_DEVICE(0x0402, &intel_haswell_d_info), /* GT1 desktop */
|
||||
INTEL_VGA_DEVICE(0x0412, &intel_haswell_d_info), /* GT2 desktop */
|
||||
|
@ -397,6 +416,15 @@ void intel_detect_pch(struct drm_device *dev)
|
|||
struct drm_i915_private *dev_priv = dev->dev_private;
|
||||
struct pci_dev *pch;
|
||||
|
||||
/* In all current cases, num_pipes is equivalent to the PCH_NOP setting
|
||||
* (which really amounts to a PCH but no South Display).
|
||||
*/
|
||||
if (INTEL_INFO(dev)->num_pipes == 0) {
|
||||
dev_priv->pch_type = PCH_NOP;
|
||||
dev_priv->num_pch_pll = 0;
|
||||
return;
|
||||
}
|
||||
|
||||
/*
|
||||
* The reason to probe ISA bridge instead of Dev31:Fun0 is to
|
||||
* make graphics device passthrough work easy for VMM, that only
|
||||
|
@ -431,11 +459,13 @@ void intel_detect_pch(struct drm_device *dev)
|
|||
dev_priv->num_pch_pll = 0;
|
||||
DRM_DEBUG_KMS("Found LynxPoint PCH\n");
|
||||
WARN_ON(!IS_HASWELL(dev));
|
||||
WARN_ON(IS_ULT(dev));
|
||||
} else if (id == INTEL_PCH_LPT_LP_DEVICE_ID_TYPE) {
|
||||
dev_priv->pch_type = PCH_LPT;
|
||||
dev_priv->num_pch_pll = 0;
|
||||
DRM_DEBUG_KMS("Found LynxPoint LP PCH\n");
|
||||
WARN_ON(!IS_HASWELL(dev));
|
||||
WARN_ON(!IS_ULT(dev));
|
||||
}
|
||||
BUG_ON(dev_priv->num_pch_pll > I915_NUM_PLLS);
|
||||
}
|
||||
|
@ -901,7 +931,11 @@ int i915_reset(struct drm_device *dev)
|
|||
ring->init(ring);
|
||||
|
||||
i915_gem_context_init(dev);
|
||||
i915_gem_init_ppgtt(dev);
|
||||
if (dev_priv->mm.aliasing_ppgtt) {
|
||||
ret = dev_priv->mm.aliasing_ppgtt->enable(dev);
|
||||
if (ret)
|
||||
i915_gem_cleanup_aliasing_ppgtt(dev);
|
||||
}
|
||||
|
||||
/*
|
||||
* It would make sense to re-init all the other hw state, at
|
||||
|
|
|
@ -195,9 +195,9 @@ struct drm_i915_master_private {
|
|||
struct _drm_i915_sarea *sarea_priv;
|
||||
};
|
||||
#define I915_FENCE_REG_NONE -1
|
||||
#define I915_MAX_NUM_FENCES 16
|
||||
/* 16 fences + sign bit for FENCE_REG_NONE */
|
||||
#define I915_MAX_NUM_FENCE_BITS 5
|
||||
#define I915_MAX_NUM_FENCES 32
|
||||
/* 32 fences + sign bit for FENCE_REG_NONE */
|
||||
#define I915_MAX_NUM_FENCE_BITS 6
|
||||
|
||||
struct drm_i915_fence_reg {
|
||||
struct list_head lru_list;
|
||||
|
@ -449,6 +449,7 @@ struct i915_hw_ppgtt {
|
|||
struct sg_table *st,
|
||||
unsigned int pg_start,
|
||||
enum i915_cache_level cache_level);
|
||||
int (*enable)(struct drm_device *dev);
|
||||
void (*cleanup)(struct i915_hw_ppgtt *ppgtt);
|
||||
};
|
||||
|
||||
|
@ -479,6 +480,7 @@ enum intel_pch {
|
|||
PCH_IBX, /* Ibexpeak PCH */
|
||||
PCH_CPT, /* Cougarpoint PCH */
|
||||
PCH_LPT, /* Lynxpoint PCH */
|
||||
PCH_NOP,
|
||||
};
|
||||
|
||||
enum intel_sbi_destination {
|
||||
|
@ -666,6 +668,7 @@ struct intel_gen6_power_mgmt {
|
|||
u8 cur_delay;
|
||||
u8 min_delay;
|
||||
u8 max_delay;
|
||||
u8 hw_max;
|
||||
|
||||
struct delayed_work delayed_resume_work;
|
||||
|
||||
|
@ -929,6 +932,16 @@ typedef struct drm_i915_private {
|
|||
|
||||
struct work_struct hotplug_work;
|
||||
bool enable_hotplug_processing;
|
||||
struct {
|
||||
unsigned long hpd_last_jiffies;
|
||||
int hpd_cnt;
|
||||
enum {
|
||||
HPD_ENABLED = 0,
|
||||
HPD_DISABLED = 1,
|
||||
HPD_MARK_DISABLED = 2
|
||||
} hpd_mark;
|
||||
} hpd_stats[HPD_NUM_PINS];
|
||||
struct timer_list hotplug_reenable_timer;
|
||||
|
||||
int num_pch_pll;
|
||||
int num_plane;
|
||||
|
@ -963,6 +976,7 @@ typedef struct drm_i915_private {
|
|||
unsigned int int_crt_support:1;
|
||||
unsigned int lvds_use_ssc:1;
|
||||
unsigned int display_clock_mode:1;
|
||||
unsigned int fdi_rx_polarity_inverted:1;
|
||||
int lvds_ssc_freq;
|
||||
unsigned int bios_lvds_val; /* initial [PCH_]LVDS reg val in VBIOS */
|
||||
struct {
|
||||
|
@ -1373,6 +1387,7 @@ struct drm_i915_file_private {
|
|||
#define HAS_PCH_LPT(dev) (INTEL_PCH_TYPE(dev) == PCH_LPT)
|
||||
#define HAS_PCH_CPT(dev) (INTEL_PCH_TYPE(dev) == PCH_CPT)
|
||||
#define HAS_PCH_IBX(dev) (INTEL_PCH_TYPE(dev) == PCH_IBX)
|
||||
#define HAS_PCH_NOP(dev) (INTEL_PCH_TYPE(dev) == PCH_NOP)
|
||||
#define HAS_PCH_SPLIT(dev) (INTEL_PCH_TYPE(dev) != PCH_NONE)
|
||||
|
||||
#define HAS_FORCE_WAKE(dev) (INTEL_INFO(dev)->has_force_wake)
|
||||
|
@ -1640,7 +1655,6 @@ int __must_check i915_gem_init(struct drm_device *dev);
|
|||
int __must_check i915_gem_init_hw(struct drm_device *dev);
|
||||
void i915_gem_l3_remap(struct drm_device *dev);
|
||||
void i915_gem_init_swizzling(struct drm_device *dev);
|
||||
void i915_gem_init_ppgtt(struct drm_device *dev);
|
||||
void i915_gem_cleanup_ringbuffer(struct drm_device *dev);
|
||||
int __must_check i915_gpu_idle(struct drm_device *dev);
|
||||
int __must_check i915_gem_idle(struct drm_device *dev);
|
||||
|
|
|
@ -2683,17 +2683,35 @@ static inline int fence_number(struct drm_i915_private *dev_priv,
|
|||
return fence - dev_priv->fence_regs;
|
||||
}
|
||||
|
||||
static void i915_gem_write_fence__ipi(void *data)
|
||||
{
|
||||
wbinvd();
|
||||
}
|
||||
|
||||
static void i915_gem_object_update_fence(struct drm_i915_gem_object *obj,
|
||||
struct drm_i915_fence_reg *fence,
|
||||
bool enable)
|
||||
{
|
||||
struct drm_i915_private *dev_priv = obj->base.dev->dev_private;
|
||||
int reg = fence_number(dev_priv, fence);
|
||||
struct drm_device *dev = obj->base.dev;
|
||||
struct drm_i915_private *dev_priv = dev->dev_private;
|
||||
int fence_reg = fence_number(dev_priv, fence);
|
||||
|
||||
i915_gem_write_fence(obj->base.dev, reg, enable ? obj : NULL);
|
||||
/* In order to fully serialize access to the fenced region and
|
||||
* the update to the fence register we need to take extreme
|
||||
* measures on SNB+. In theory, the write to the fence register
|
||||
* flushes all memory transactions before, and coupled with the
|
||||
* mb() placed around the register write we serialise all memory
|
||||
* operations with respect to the changes in the tiler. Yet, on
|
||||
* SNB+ we need to take a step further and emit an explicit wbinvd()
|
||||
* on each processor in order to manually flush all memory
|
||||
* transactions before updating the fence register.
|
||||
*/
|
||||
if (HAS_LLC(obj->base.dev))
|
||||
on_each_cpu(i915_gem_write_fence__ipi, NULL, 1);
|
||||
i915_gem_write_fence(dev, fence_reg, enable ? obj : NULL);
|
||||
|
||||
if (enable) {
|
||||
obj->fence_reg = reg;
|
||||
obj->fence_reg = fence_reg;
|
||||
fence->obj = obj;
|
||||
list_move_tail(&fence->lru_list, &dev_priv->mm.fence_list);
|
||||
} else {
|
||||
|
@ -3992,6 +4010,12 @@ i915_gem_init_hw(struct drm_device *dev)
|
|||
if (IS_HASWELL(dev) && (I915_READ(0x120010) == 1))
|
||||
I915_WRITE(0x9008, I915_READ(0x9008) | 0xf0000);
|
||||
|
||||
if (HAS_PCH_NOP(dev)) {
|
||||
u32 temp = I915_READ(GEN7_MSG_CTL);
|
||||
temp &= ~(WAIT_FOR_PCH_FLR_ACK | WAIT_FOR_PCH_RESET_ACK);
|
||||
I915_WRITE(GEN7_MSG_CTL, temp);
|
||||
}
|
||||
|
||||
i915_gem_l3_remap(dev);
|
||||
|
||||
i915_gem_init_swizzling(dev);
|
||||
|
@ -4005,7 +4029,13 @@ i915_gem_init_hw(struct drm_device *dev)
|
|||
* contexts before PPGTT.
|
||||
*/
|
||||
i915_gem_context_init(dev);
|
||||
i915_gem_init_ppgtt(dev);
|
||||
if (dev_priv->mm.aliasing_ppgtt) {
|
||||
ret = dev_priv->mm.aliasing_ppgtt->enable(dev);
|
||||
if (ret) {
|
||||
i915_gem_cleanup_aliasing_ppgtt(dev);
|
||||
DRM_INFO("PPGTT enable failed. This is not fatal, but unexpected\n");
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -4160,7 +4190,9 @@ i915_gem_load(struct drm_device *dev)
|
|||
if (!drm_core_check_feature(dev, DRIVER_MODESET))
|
||||
dev_priv->fence_reg_start = 3;
|
||||
|
||||
if (INTEL_INFO(dev)->gen >= 4 || IS_I945G(dev) || IS_I945GM(dev) || IS_G33(dev))
|
||||
if (INTEL_INFO(dev)->gen >= 7 && !IS_VALLEYVIEW(dev))
|
||||
dev_priv->num_fence_regs = 32;
|
||||
else if (INTEL_INFO(dev)->gen >= 4 || IS_I945G(dev) || IS_I945GM(dev) || IS_G33(dev))
|
||||
dev_priv->num_fence_regs = 16;
|
||||
else
|
||||
dev_priv->num_fence_regs = 8;
|
||||
|
|
|
@ -152,6 +152,13 @@ create_hw_context(struct drm_device *dev,
|
|||
return ERR_PTR(-ENOMEM);
|
||||
}
|
||||
|
||||
if (INTEL_INFO(dev)->gen >= 7) {
|
||||
ret = i915_gem_object_set_cache_level(ctx->obj,
|
||||
I915_CACHE_LLC_MLC);
|
||||
if (ret)
|
||||
goto err_out;
|
||||
}
|
||||
|
||||
/* The ring associated with the context object is handled by the normal
|
||||
* object tracking code. We give an initial ring value simple to pass an
|
||||
* assertion in the context switch code.
|
||||
|
|
|
@ -28,7 +28,7 @@
|
|||
#include "i915_trace.h"
|
||||
#include "intel_drv.h"
|
||||
|
||||
typedef uint32_t gtt_pte_t;
|
||||
typedef uint32_t gen6_gtt_pte_t;
|
||||
|
||||
/* PPGTT stuff */
|
||||
#define GEN6_GTT_ADDR_ENCODE(addr) ((addr) | (((addr) >> 28) & 0xff0))
|
||||
|
@ -44,11 +44,11 @@ typedef uint32_t gtt_pte_t;
|
|||
#define GEN6_PTE_CACHE_LLC_MLC (3 << 1)
|
||||
#define GEN6_PTE_ADDR_ENCODE(addr) GEN6_GTT_ADDR_ENCODE(addr)
|
||||
|
||||
static inline gtt_pte_t gen6_pte_encode(struct drm_device *dev,
|
||||
dma_addr_t addr,
|
||||
enum i915_cache_level level)
|
||||
static inline gen6_gtt_pte_t gen6_pte_encode(struct drm_device *dev,
|
||||
dma_addr_t addr,
|
||||
enum i915_cache_level level)
|
||||
{
|
||||
gtt_pte_t pte = GEN6_PTE_VALID;
|
||||
gen6_gtt_pte_t pte = GEN6_PTE_VALID;
|
||||
pte |= GEN6_PTE_ADDR_ENCODE(addr);
|
||||
|
||||
switch (level) {
|
||||
|
@ -72,17 +72,84 @@ static inline gtt_pte_t gen6_pte_encode(struct drm_device *dev,
|
|||
BUG();
|
||||
}
|
||||
|
||||
|
||||
return pte;
|
||||
}
|
||||
|
||||
static int gen6_ppgtt_enable(struct drm_device *dev)
|
||||
{
|
||||
drm_i915_private_t *dev_priv = dev->dev_private;
|
||||
uint32_t pd_offset;
|
||||
struct intel_ring_buffer *ring;
|
||||
struct i915_hw_ppgtt *ppgtt = dev_priv->mm.aliasing_ppgtt;
|
||||
gen6_gtt_pte_t __iomem *pd_addr;
|
||||
uint32_t pd_entry;
|
||||
int i;
|
||||
|
||||
pd_addr = (gen6_gtt_pte_t __iomem*)dev_priv->gtt.gsm +
|
||||
ppgtt->pd_offset / sizeof(gen6_gtt_pte_t);
|
||||
for (i = 0; i < ppgtt->num_pd_entries; i++) {
|
||||
dma_addr_t pt_addr;
|
||||
|
||||
pt_addr = ppgtt->pt_dma_addr[i];
|
||||
pd_entry = GEN6_PDE_ADDR_ENCODE(pt_addr);
|
||||
pd_entry |= GEN6_PDE_VALID;
|
||||
|
||||
writel(pd_entry, pd_addr + i);
|
||||
}
|
||||
readl(pd_addr);
|
||||
|
||||
pd_offset = ppgtt->pd_offset;
|
||||
pd_offset /= 64; /* in cachelines, */
|
||||
pd_offset <<= 16;
|
||||
|
||||
if (INTEL_INFO(dev)->gen == 6) {
|
||||
uint32_t ecochk, gab_ctl, ecobits;
|
||||
|
||||
ecobits = I915_READ(GAC_ECO_BITS);
|
||||
I915_WRITE(GAC_ECO_BITS, ecobits | ECOBITS_SNB_BIT |
|
||||
ECOBITS_PPGTT_CACHE64B);
|
||||
|
||||
gab_ctl = I915_READ(GAB_CTL);
|
||||
I915_WRITE(GAB_CTL, gab_ctl | GAB_CTL_CONT_AFTER_PAGEFAULT);
|
||||
|
||||
ecochk = I915_READ(GAM_ECOCHK);
|
||||
I915_WRITE(GAM_ECOCHK, ecochk | ECOCHK_SNB_BIT |
|
||||
ECOCHK_PPGTT_CACHE64B);
|
||||
I915_WRITE(GFX_MODE, _MASKED_BIT_ENABLE(GFX_PPGTT_ENABLE));
|
||||
} else if (INTEL_INFO(dev)->gen >= 7) {
|
||||
uint32_t ecochk, ecobits;
|
||||
|
||||
ecobits = I915_READ(GAC_ECO_BITS);
|
||||
I915_WRITE(GAC_ECO_BITS, ecobits | ECOBITS_PPGTT_CACHE64B);
|
||||
|
||||
ecochk = I915_READ(GAM_ECOCHK);
|
||||
if (IS_HASWELL(dev)) {
|
||||
ecochk |= ECOCHK_PPGTT_WB_HSW;
|
||||
} else {
|
||||
ecochk |= ECOCHK_PPGTT_LLC_IVB;
|
||||
ecochk &= ~ECOCHK_PPGTT_GFDT_IVB;
|
||||
}
|
||||
I915_WRITE(GAM_ECOCHK, ecochk);
|
||||
/* GFX_MODE is per-ring on gen7+ */
|
||||
}
|
||||
|
||||
for_each_ring(ring, dev_priv, i) {
|
||||
if (INTEL_INFO(dev)->gen >= 7)
|
||||
I915_WRITE(RING_MODE_GEN7(ring),
|
||||
_MASKED_BIT_ENABLE(GFX_PPGTT_ENABLE));
|
||||
|
||||
I915_WRITE(RING_PP_DIR_DCLV(ring), PP_DIR_DCLV_2G);
|
||||
I915_WRITE(RING_PP_DIR_BASE(ring), pd_offset);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* PPGTT support for Sandybdrige/Gen6 and later */
|
||||
static void gen6_ppgtt_clear_range(struct i915_hw_ppgtt *ppgtt,
|
||||
unsigned first_entry,
|
||||
unsigned num_entries)
|
||||
{
|
||||
gtt_pte_t *pt_vaddr;
|
||||
gtt_pte_t scratch_pte;
|
||||
gen6_gtt_pte_t *pt_vaddr, scratch_pte;
|
||||
unsigned act_pt = first_entry / I915_PPGTT_PT_ENTRIES;
|
||||
unsigned first_pte = first_entry % I915_PPGTT_PT_ENTRIES;
|
||||
unsigned last_pte, i;
|
||||
|
@ -114,7 +181,7 @@ static void gen6_ppgtt_insert_entries(struct i915_hw_ppgtt *ppgtt,
|
|||
unsigned first_entry,
|
||||
enum i915_cache_level cache_level)
|
||||
{
|
||||
gtt_pte_t *pt_vaddr;
|
||||
gen6_gtt_pte_t *pt_vaddr;
|
||||
unsigned act_pt = first_entry / I915_PPGTT_PT_ENTRIES;
|
||||
unsigned act_pte = first_entry % I915_PPGTT_PT_ENTRIES;
|
||||
struct sg_page_iter sg_iter;
|
||||
|
@ -170,6 +237,7 @@ static int gen6_ppgtt_init(struct i915_hw_ppgtt *ppgtt)
|
|||
gtt_total_entries(dev_priv->gtt) - I915_PPGTT_PD_ENTRIES;
|
||||
|
||||
ppgtt->num_pd_entries = I915_PPGTT_PD_ENTRIES;
|
||||
ppgtt->enable = gen6_ppgtt_enable;
|
||||
ppgtt->clear_range = gen6_ppgtt_clear_range;
|
||||
ppgtt->insert_entries = gen6_ppgtt_insert_entries;
|
||||
ppgtt->cleanup = gen6_ppgtt_cleanup;
|
||||
|
@ -203,12 +271,10 @@ static int gen6_ppgtt_init(struct i915_hw_ppgtt *ppgtt)
|
|||
ppgtt->pt_dma_addr[i] = pt_addr;
|
||||
}
|
||||
|
||||
ppgtt->scratch_page_dma_addr = dev_priv->gtt.scratch_page_dma;
|
||||
|
||||
ppgtt->clear_range(ppgtt, 0,
|
||||
ppgtt->num_pd_entries*I915_PPGTT_PT_ENTRIES);
|
||||
|
||||
ppgtt->pd_offset = (first_pd_entry_in_global_pt)*sizeof(gtt_pte_t);
|
||||
ppgtt->pd_offset = first_pd_entry_in_global_pt * sizeof(gen6_gtt_pte_t);
|
||||
|
||||
return 0;
|
||||
|
||||
|
@ -240,8 +306,13 @@ static int i915_gem_init_aliasing_ppgtt(struct drm_device *dev)
|
|||
return -ENOMEM;
|
||||
|
||||
ppgtt->dev = dev;
|
||||
ppgtt->scratch_page_dma_addr = dev_priv->gtt.scratch_page_dma;
|
||||
|
||||
if (INTEL_INFO(dev)->gen < 8)
|
||||
ret = gen6_ppgtt_init(ppgtt);
|
||||
else
|
||||
BUG();
|
||||
|
||||
ret = gen6_ppgtt_init(ppgtt);
|
||||
if (ret)
|
||||
kfree(ppgtt);
|
||||
else
|
||||
|
@ -259,6 +330,7 @@ void i915_gem_cleanup_aliasing_ppgtt(struct drm_device *dev)
|
|||
return;
|
||||
|
||||
ppgtt->cleanup(ppgtt);
|
||||
dev_priv->mm.aliasing_ppgtt = NULL;
|
||||
}
|
||||
|
||||
void i915_ppgtt_bind_object(struct i915_hw_ppgtt *ppgtt,
|
||||
|
@ -278,64 +350,6 @@ void i915_ppgtt_unbind_object(struct i915_hw_ppgtt *ppgtt,
|
|||
obj->base.size >> PAGE_SHIFT);
|
||||
}
|
||||
|
||||
void i915_gem_init_ppgtt(struct drm_device *dev)
|
||||
{
|
||||
drm_i915_private_t *dev_priv = dev->dev_private;
|
||||
uint32_t pd_offset;
|
||||
struct intel_ring_buffer *ring;
|
||||
struct i915_hw_ppgtt *ppgtt = dev_priv->mm.aliasing_ppgtt;
|
||||
gtt_pte_t __iomem *pd_addr;
|
||||
uint32_t pd_entry;
|
||||
int i;
|
||||
|
||||
if (!dev_priv->mm.aliasing_ppgtt)
|
||||
return;
|
||||
|
||||
|
||||
pd_addr = (gtt_pte_t __iomem*)dev_priv->gtt.gsm + ppgtt->pd_offset/sizeof(gtt_pte_t);
|
||||
for (i = 0; i < ppgtt->num_pd_entries; i++) {
|
||||
dma_addr_t pt_addr;
|
||||
|
||||
pt_addr = ppgtt->pt_dma_addr[i];
|
||||
pd_entry = GEN6_PDE_ADDR_ENCODE(pt_addr);
|
||||
pd_entry |= GEN6_PDE_VALID;
|
||||
|
||||
writel(pd_entry, pd_addr + i);
|
||||
}
|
||||
readl(pd_addr);
|
||||
|
||||
pd_offset = ppgtt->pd_offset;
|
||||
pd_offset /= 64; /* in cachelines, */
|
||||
pd_offset <<= 16;
|
||||
|
||||
if (INTEL_INFO(dev)->gen == 6) {
|
||||
uint32_t ecochk, gab_ctl, ecobits;
|
||||
|
||||
ecobits = I915_READ(GAC_ECO_BITS);
|
||||
I915_WRITE(GAC_ECO_BITS, ecobits | ECOBITS_PPGTT_CACHE64B);
|
||||
|
||||
gab_ctl = I915_READ(GAB_CTL);
|
||||
I915_WRITE(GAB_CTL, gab_ctl | GAB_CTL_CONT_AFTER_PAGEFAULT);
|
||||
|
||||
ecochk = I915_READ(GAM_ECOCHK);
|
||||
I915_WRITE(GAM_ECOCHK, ecochk | ECOCHK_SNB_BIT |
|
||||
ECOCHK_PPGTT_CACHE64B);
|
||||
I915_WRITE(GFX_MODE, _MASKED_BIT_ENABLE(GFX_PPGTT_ENABLE));
|
||||
} else if (INTEL_INFO(dev)->gen >= 7) {
|
||||
I915_WRITE(GAM_ECOCHK, ECOCHK_PPGTT_CACHE64B);
|
||||
/* GFX_MODE is per-ring on gen7+ */
|
||||
}
|
||||
|
||||
for_each_ring(ring, dev_priv, i) {
|
||||
if (INTEL_INFO(dev)->gen >= 7)
|
||||
I915_WRITE(RING_MODE_GEN7(ring),
|
||||
_MASKED_BIT_ENABLE(GFX_PPGTT_ENABLE));
|
||||
|
||||
I915_WRITE(RING_PP_DIR_DCLV(ring), PP_DIR_DCLV_2G);
|
||||
I915_WRITE(RING_PP_DIR_BASE(ring), pd_offset);
|
||||
}
|
||||
}
|
||||
|
||||
extern int intel_iommu_gfx_mapped;
|
||||
/* Certain Gen5 chipsets require require idling the GPU before
|
||||
* unmapping anything from the GTT when VT-d is enabled.
|
||||
|
@ -416,8 +430,8 @@ static void gen6_ggtt_insert_entries(struct drm_device *dev,
|
|||
enum i915_cache_level level)
|
||||
{
|
||||
struct drm_i915_private *dev_priv = dev->dev_private;
|
||||
gtt_pte_t __iomem *gtt_entries =
|
||||
(gtt_pte_t __iomem *)dev_priv->gtt.gsm + first_entry;
|
||||
gen6_gtt_pte_t __iomem *gtt_entries =
|
||||
(gen6_gtt_pte_t __iomem *)dev_priv->gtt.gsm + first_entry;
|
||||
int i = 0;
|
||||
struct sg_page_iter sg_iter;
|
||||
dma_addr_t addr;
|
||||
|
@ -451,8 +465,8 @@ static void gen6_ggtt_clear_range(struct drm_device *dev,
|
|||
unsigned int num_entries)
|
||||
{
|
||||
struct drm_i915_private *dev_priv = dev->dev_private;
|
||||
gtt_pte_t scratch_pte;
|
||||
gtt_pte_t __iomem *gtt_base = (gtt_pte_t __iomem *) dev_priv->gtt.gsm + first_entry;
|
||||
gen6_gtt_pte_t scratch_pte, __iomem *gtt_base =
|
||||
(gen6_gtt_pte_t __iomem *) dev_priv->gtt.gsm + first_entry;
|
||||
const int max_entries = gtt_total_entries(dev_priv->gtt) - first_entry;
|
||||
int i;
|
||||
|
||||
|
@ -626,9 +640,12 @@ void i915_gem_init_global_gtt(struct drm_device *dev)
|
|||
|
||||
if (intel_enable_ppgtt(dev) && HAS_ALIASING_PPGTT(dev)) {
|
||||
int ret;
|
||||
/* PPGTT pdes are stolen from global gtt ptes, so shrink the
|
||||
* aperture accordingly when using aliasing ppgtt. */
|
||||
gtt_size -= I915_PPGTT_PD_ENTRIES*PAGE_SIZE;
|
||||
|
||||
if (INTEL_INFO(dev)->gen <= 7) {
|
||||
/* PPGTT pdes are stolen from global gtt ptes, so shrink the
|
||||
* aperture accordingly when using aliasing ppgtt. */
|
||||
gtt_size -= I915_PPGTT_PD_ENTRIES*PAGE_SIZE;
|
||||
}
|
||||
|
||||
i915_gem_setup_global_gtt(dev, 0, mappable_size, gtt_size);
|
||||
|
||||
|
@ -736,10 +753,12 @@ static int gen6_gmch_probe(struct drm_device *dev,
|
|||
else
|
||||
*stolen = gen6_get_stolen_size(snb_gmch_ctl);
|
||||
|
||||
*gtt_total = (gtt_size / sizeof(gtt_pte_t)) << PAGE_SHIFT;
|
||||
*gtt_total = (gtt_size / sizeof(gen6_gtt_pte_t)) << PAGE_SHIFT;
|
||||
|
||||
/* For Modern GENs the PTEs and register space are split in the BAR */
|
||||
gtt_bus_addr = pci_resource_start(dev->pdev, 0) +
|
||||
(pci_resource_len(dev->pdev, 0) / 2);
|
||||
|
||||
/* For GEN6+ the PTEs for the ggtt live at 2MB + BAR0 */
|
||||
gtt_bus_addr = pci_resource_start(dev->pdev, 0) + (2<<20);
|
||||
dev_priv->gtt.gsm = ioremap_wc(gtt_bus_addr, gtt_size);
|
||||
if (!dev_priv->gtt.gsm) {
|
||||
DRM_ERROR("Failed to map the gtt page table\n");
|
||||
|
@ -796,7 +815,6 @@ int i915_gem_gtt_init(struct drm_device *dev)
|
|||
{
|
||||
struct drm_i915_private *dev_priv = dev->dev_private;
|
||||
struct i915_gtt *gtt = &dev_priv->gtt;
|
||||
unsigned long gtt_size;
|
||||
int ret;
|
||||
|
||||
if (INTEL_INFO(dev)->gen <= 5) {
|
||||
|
@ -814,8 +832,6 @@ int i915_gem_gtt_init(struct drm_device *dev)
|
|||
if (ret)
|
||||
return ret;
|
||||
|
||||
gtt_size = (dev_priv->gtt.total >> PAGE_SHIFT) * sizeof(gtt_pte_t);
|
||||
|
||||
/* GMADR is the PCI mmio aperture into the global GTT. */
|
||||
DRM_INFO("Memory usable by graphics device = %zdM\n",
|
||||
dev_priv->gtt.total >> 20);
|
||||
|
|
|
@ -217,9 +217,12 @@ i915_tiling_ok(struct drm_device *dev, int stride, int size, int tiling_mode)
|
|||
tile_width = 512;
|
||||
|
||||
/* check maximum stride & object size */
|
||||
if (INTEL_INFO(dev)->gen >= 4) {
|
||||
/* i965 stores the end address of the gtt mapping in the fence
|
||||
* reg, so dont bother to check the size */
|
||||
/* i965+ stores the end address of the gtt mapping in the fence
|
||||
* reg, so dont bother to check the size */
|
||||
if (INTEL_INFO(dev)->gen >= 7) {
|
||||
if (stride / 128 > GEN7_FENCE_MAX_PITCH_VAL)
|
||||
return false;
|
||||
} else if (INTEL_INFO(dev)->gen >= 4) {
|
||||
if (stride / 128 > I965_FENCE_MAX_PITCH_VAL)
|
||||
return false;
|
||||
} else {
|
||||
|
@ -235,6 +238,9 @@ i915_tiling_ok(struct drm_device *dev, int stride, int size, int tiling_mode)
|
|||
}
|
||||
}
|
||||
|
||||
if (stride < tile_width)
|
||||
return false;
|
||||
|
||||
/* 965+ just needs multiples of tile width */
|
||||
if (INTEL_INFO(dev)->gen >= 4) {
|
||||
if (stride & (tile_width - 1))
|
||||
|
@ -243,9 +249,6 @@ i915_tiling_ok(struct drm_device *dev, int stride, int size, int tiling_mode)
|
|||
}
|
||||
|
||||
/* Pre-965 needs power of two tile widths */
|
||||
if (stride < tile_width)
|
||||
return false;
|
||||
|
||||
if (stride & (stride - 1))
|
||||
return false;
|
||||
|
||||
|
|
|
@ -88,7 +88,8 @@ static const u32 hpd_status_i915[] = { /* i915 and valleyview are the same */
|
|||
[HPD_PORT_D] = PORTD_HOTPLUG_INT_STATUS
|
||||
};
|
||||
|
||||
|
||||
static void ibx_hpd_irq_setup(struct drm_device *dev);
|
||||
static void i915_hpd_irq_setup(struct drm_device *dev);
|
||||
|
||||
/* For display hotplug interrupt */
|
||||
static void
|
||||
|
@ -336,13 +337,19 @@ static int i915_get_vblank_timestamp(struct drm_device *dev, int pipe,
|
|||
/*
|
||||
* Handle hotplug events outside the interrupt handler proper.
|
||||
*/
|
||||
#define I915_REENABLE_HOTPLUG_DELAY (2*60*1000)
|
||||
|
||||
static void i915_hotplug_work_func(struct work_struct *work)
|
||||
{
|
||||
drm_i915_private_t *dev_priv = container_of(work, drm_i915_private_t,
|
||||
hotplug_work);
|
||||
struct drm_device *dev = dev_priv->dev;
|
||||
struct drm_mode_config *mode_config = &dev->mode_config;
|
||||
struct intel_encoder *encoder;
|
||||
struct intel_connector *intel_connector;
|
||||
struct intel_encoder *intel_encoder;
|
||||
struct drm_connector *connector;
|
||||
unsigned long irqflags;
|
||||
bool hpd_disabled = false;
|
||||
|
||||
/* HPD irq before everything is fully set up. */
|
||||
if (!dev_priv->enable_hotplug_processing)
|
||||
|
@ -351,9 +358,36 @@ static void i915_hotplug_work_func(struct work_struct *work)
|
|||
mutex_lock(&mode_config->mutex);
|
||||
DRM_DEBUG_KMS("running encoder hotplug functions\n");
|
||||
|
||||
list_for_each_entry(encoder, &mode_config->encoder_list, base.head)
|
||||
if (encoder->hot_plug)
|
||||
encoder->hot_plug(encoder);
|
||||
spin_lock_irqsave(&dev_priv->irq_lock, irqflags);
|
||||
list_for_each_entry(connector, &mode_config->connector_list, head) {
|
||||
intel_connector = to_intel_connector(connector);
|
||||
intel_encoder = intel_connector->encoder;
|
||||
if (intel_encoder->hpd_pin > HPD_NONE &&
|
||||
dev_priv->hpd_stats[intel_encoder->hpd_pin].hpd_mark == HPD_MARK_DISABLED &&
|
||||
connector->polled == DRM_CONNECTOR_POLL_HPD) {
|
||||
DRM_INFO("HPD interrupt storm detected on connector %s: "
|
||||
"switching from hotplug detection to polling\n",
|
||||
drm_get_connector_name(connector));
|
||||
dev_priv->hpd_stats[intel_encoder->hpd_pin].hpd_mark = HPD_DISABLED;
|
||||
connector->polled = DRM_CONNECTOR_POLL_CONNECT
|
||||
| DRM_CONNECTOR_POLL_DISCONNECT;
|
||||
hpd_disabled = true;
|
||||
}
|
||||
}
|
||||
/* if there were no outputs to poll, poll was disabled,
|
||||
* therefore make sure it's enabled when disabling HPD on
|
||||
* some connectors */
|
||||
if (hpd_disabled) {
|
||||
drm_kms_helper_poll_enable(dev);
|
||||
mod_timer(&dev_priv->hotplug_reenable_timer,
|
||||
jiffies + msecs_to_jiffies(I915_REENABLE_HOTPLUG_DELAY));
|
||||
}
|
||||
|
||||
spin_unlock_irqrestore(&dev_priv->irq_lock, irqflags);
|
||||
|
||||
list_for_each_entry(intel_encoder, &mode_config->encoder_list, base.head)
|
||||
if (intel_encoder->hot_plug)
|
||||
intel_encoder->hot_plug(intel_encoder);
|
||||
|
||||
mutex_unlock(&mode_config->mutex);
|
||||
|
||||
|
@ -582,6 +616,45 @@ static void gen6_queue_rps_work(struct drm_i915_private *dev_priv,
|
|||
queue_work(dev_priv->wq, &dev_priv->rps.work);
|
||||
}
|
||||
|
||||
#define HPD_STORM_DETECT_PERIOD 1000
|
||||
#define HPD_STORM_THRESHOLD 5
|
||||
|
||||
static inline bool hotplug_irq_storm_detect(struct drm_device *dev,
|
||||
u32 hotplug_trigger,
|
||||
const u32 *hpd)
|
||||
{
|
||||
drm_i915_private_t *dev_priv = dev->dev_private;
|
||||
unsigned long irqflags;
|
||||
int i;
|
||||
bool ret = false;
|
||||
|
||||
spin_lock_irqsave(&dev_priv->irq_lock, irqflags);
|
||||
|
||||
for (i = 1; i < HPD_NUM_PINS; i++) {
|
||||
|
||||
if (!(hpd[i] & hotplug_trigger) ||
|
||||
dev_priv->hpd_stats[i].hpd_mark != HPD_ENABLED)
|
||||
continue;
|
||||
|
||||
if (!time_in_range(jiffies, dev_priv->hpd_stats[i].hpd_last_jiffies,
|
||||
dev_priv->hpd_stats[i].hpd_last_jiffies
|
||||
+ msecs_to_jiffies(HPD_STORM_DETECT_PERIOD))) {
|
||||
dev_priv->hpd_stats[i].hpd_last_jiffies = jiffies;
|
||||
dev_priv->hpd_stats[i].hpd_cnt = 0;
|
||||
} else if (dev_priv->hpd_stats[i].hpd_cnt > HPD_STORM_THRESHOLD) {
|
||||
dev_priv->hpd_stats[i].hpd_mark = HPD_MARK_DISABLED;
|
||||
DRM_DEBUG_KMS("HPD interrupt storm detected on PIN %d\n", i);
|
||||
ret = true;
|
||||
} else {
|
||||
dev_priv->hpd_stats[i].hpd_cnt++;
|
||||
}
|
||||
}
|
||||
|
||||
spin_unlock_irqrestore(&dev_priv->irq_lock, irqflags);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void gmbus_irq_handler(struct drm_device *dev)
|
||||
{
|
||||
struct drm_i915_private *dev_priv = (drm_i915_private_t *) dev->dev_private;
|
||||
|
@ -650,13 +723,16 @@ static irqreturn_t valleyview_irq_handler(int irq, void *arg)
|
|||
/* Consume port. Then clear IIR or we'll miss events */
|
||||
if (iir & I915_DISPLAY_PORT_INTERRUPT) {
|
||||
u32 hotplug_status = I915_READ(PORT_HOTPLUG_STAT);
|
||||
u32 hotplug_trigger = hotplug_status & HOTPLUG_INT_STATUS_I915;
|
||||
|
||||
DRM_DEBUG_DRIVER("hotplug event received, stat 0x%08x\n",
|
||||
hotplug_status);
|
||||
if (hotplug_status & HOTPLUG_INT_STATUS_I915)
|
||||
if (hotplug_trigger) {
|
||||
if (hotplug_irq_storm_detect(dev, hotplug_trigger, hpd_status_i915))
|
||||
i915_hpd_irq_setup(dev);
|
||||
queue_work(dev_priv->wq,
|
||||
&dev_priv->hotplug_work);
|
||||
|
||||
}
|
||||
I915_WRITE(PORT_HOTPLUG_STAT, hotplug_status);
|
||||
I915_READ(PORT_HOTPLUG_STAT);
|
||||
}
|
||||
|
@ -680,10 +756,13 @@ static void ibx_irq_handler(struct drm_device *dev, u32 pch_iir)
|
|||
{
|
||||
drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private;
|
||||
int pipe;
|
||||
u32 hotplug_trigger = pch_iir & SDE_HOTPLUG_MASK;
|
||||
|
||||
if (pch_iir & SDE_HOTPLUG_MASK)
|
||||
if (hotplug_trigger) {
|
||||
if (hotplug_irq_storm_detect(dev, hotplug_trigger, hpd_ibx))
|
||||
ibx_hpd_irq_setup(dev);
|
||||
queue_work(dev_priv->wq, &dev_priv->hotplug_work);
|
||||
|
||||
}
|
||||
if (pch_iir & SDE_AUDIO_POWER_MASK)
|
||||
DRM_DEBUG_DRIVER("PCH audio power change on port %d\n",
|
||||
(pch_iir & SDE_AUDIO_POWER_MASK) >>
|
||||
|
@ -726,10 +805,13 @@ static void cpt_irq_handler(struct drm_device *dev, u32 pch_iir)
|
|||
{
|
||||
drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private;
|
||||
int pipe;
|
||||
u32 hotplug_trigger = pch_iir & SDE_HOTPLUG_MASK_CPT;
|
||||
|
||||
if (pch_iir & SDE_HOTPLUG_MASK_CPT)
|
||||
if (hotplug_trigger) {
|
||||
if (hotplug_irq_storm_detect(dev, hotplug_trigger, hpd_cpt))
|
||||
ibx_hpd_irq_setup(dev);
|
||||
queue_work(dev_priv->wq, &dev_priv->hotplug_work);
|
||||
|
||||
}
|
||||
if (pch_iir & SDE_AUDIO_POWER_MASK_CPT)
|
||||
DRM_DEBUG_DRIVER("PCH audio power change on port %d\n",
|
||||
(pch_iir & SDE_AUDIO_POWER_MASK_CPT) >>
|
||||
|
@ -758,7 +840,7 @@ static irqreturn_t ivybridge_irq_handler(int irq, void *arg)
|
|||
{
|
||||
struct drm_device *dev = (struct drm_device *) arg;
|
||||
drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private;
|
||||
u32 de_iir, gt_iir, de_ier, pm_iir, sde_ier;
|
||||
u32 de_iir, gt_iir, de_ier, pm_iir, sde_ier = 0;
|
||||
irqreturn_t ret = IRQ_NONE;
|
||||
int i;
|
||||
|
||||
|
@ -773,9 +855,11 @@ static irqreturn_t ivybridge_irq_handler(int irq, void *arg)
|
|||
* able to process them after we restore SDEIER (as soon as we restore
|
||||
* it, we'll get an interrupt if SDEIIR still has something to process
|
||||
* due to its back queue). */
|
||||
sde_ier = I915_READ(SDEIER);
|
||||
I915_WRITE(SDEIER, 0);
|
||||
POSTING_READ(SDEIER);
|
||||
if (!HAS_PCH_NOP(dev)) {
|
||||
sde_ier = I915_READ(SDEIER);
|
||||
I915_WRITE(SDEIER, 0);
|
||||
POSTING_READ(SDEIER);
|
||||
}
|
||||
|
||||
gt_iir = I915_READ(GTIIR);
|
||||
if (gt_iir) {
|
||||
|
@ -802,7 +886,7 @@ static irqreturn_t ivybridge_irq_handler(int irq, void *arg)
|
|||
}
|
||||
|
||||
/* check event from PCH */
|
||||
if (de_iir & DE_PCH_EVENT_IVB) {
|
||||
if (!HAS_PCH_NOP(dev) && (de_iir & DE_PCH_EVENT_IVB)) {
|
||||
u32 pch_iir = I915_READ(SDEIIR);
|
||||
|
||||
cpt_irq_handler(dev, pch_iir);
|
||||
|
@ -825,8 +909,10 @@ static irqreturn_t ivybridge_irq_handler(int irq, void *arg)
|
|||
|
||||
I915_WRITE(DEIER, de_ier);
|
||||
POSTING_READ(DEIER);
|
||||
I915_WRITE(SDEIER, sde_ier);
|
||||
POSTING_READ(SDEIER);
|
||||
if (!HAS_PCH_NOP(dev)) {
|
||||
I915_WRITE(SDEIER, sde_ier);
|
||||
POSTING_READ(SDEIER);
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
@ -1209,7 +1295,7 @@ static void i915_gem_record_fences(struct drm_device *dev,
|
|||
switch (INTEL_INFO(dev)->gen) {
|
||||
case 7:
|
||||
case 6:
|
||||
for (i = 0; i < 16; i++)
|
||||
for (i = 0; i < dev_priv->num_fence_regs; i++)
|
||||
error->fence[i] = I915_READ64(FENCE_REG_SANDYBRIDGE_0 + (i * 8));
|
||||
break;
|
||||
case 5:
|
||||
|
@ -2027,6 +2113,9 @@ static void ironlake_irq_preinstall(struct drm_device *dev)
|
|||
I915_WRITE(GTIER, 0x0);
|
||||
POSTING_READ(GTIER);
|
||||
|
||||
if (HAS_PCH_NOP(dev))
|
||||
return;
|
||||
|
||||
/* south display irq */
|
||||
I915_WRITE(SDEIMR, 0xffffffff);
|
||||
/*
|
||||
|
@ -2080,11 +2169,15 @@ static void ibx_hpd_irq_setup(struct drm_device *dev)
|
|||
u32 hotplug;
|
||||
|
||||
if (HAS_PCH_IBX(dev)) {
|
||||
mask &= ~SDE_HOTPLUG_MASK;
|
||||
list_for_each_entry(intel_encoder, &mode_config->encoder_list, base.head)
|
||||
mask |= hpd_ibx[intel_encoder->hpd_pin];
|
||||
if (dev_priv->hpd_stats[intel_encoder->hpd_pin].hpd_mark == HPD_ENABLED)
|
||||
mask |= hpd_ibx[intel_encoder->hpd_pin];
|
||||
} else {
|
||||
mask &= ~SDE_HOTPLUG_MASK_CPT;
|
||||
list_for_each_entry(intel_encoder, &mode_config->encoder_list, base.head)
|
||||
mask |= hpd_cpt[intel_encoder->hpd_pin];
|
||||
if (dev_priv->hpd_stats[intel_encoder->hpd_pin].hpd_mark == HPD_ENABLED)
|
||||
mask |= hpd_cpt[intel_encoder->hpd_pin];
|
||||
}
|
||||
|
||||
I915_WRITE(SDEIMR, ~mask);
|
||||
|
@ -2112,6 +2205,10 @@ static void ibx_irq_postinstall(struct drm_device *dev)
|
|||
mask = SDE_GMBUS | SDE_AUX_MASK;
|
||||
else
|
||||
mask = SDE_GMBUS_CPT | SDE_AUX_MASK_CPT;
|
||||
|
||||
if (HAS_PCH_NOP(dev))
|
||||
return;
|
||||
|
||||
I915_WRITE(SDEIIR, I915_READ(SDEIIR));
|
||||
I915_WRITE(SDEIMR, ~mask);
|
||||
}
|
||||
|
@ -2275,6 +2372,8 @@ static void valleyview_irq_uninstall(struct drm_device *dev)
|
|||
if (!dev_priv)
|
||||
return;
|
||||
|
||||
del_timer_sync(&dev_priv->hotplug_reenable_timer);
|
||||
|
||||
for_each_pipe(pipe)
|
||||
I915_WRITE(PIPESTAT(pipe), 0xffff);
|
||||
|
||||
|
@ -2296,6 +2395,8 @@ static void ironlake_irq_uninstall(struct drm_device *dev)
|
|||
if (!dev_priv)
|
||||
return;
|
||||
|
||||
del_timer_sync(&dev_priv->hotplug_reenable_timer);
|
||||
|
||||
I915_WRITE(HWSTAM, 0xffffffff);
|
||||
|
||||
I915_WRITE(DEIMR, 0xffffffff);
|
||||
|
@ -2306,6 +2407,9 @@ static void ironlake_irq_uninstall(struct drm_device *dev)
|
|||
I915_WRITE(GTIER, 0x0);
|
||||
I915_WRITE(GTIIR, I915_READ(GTIIR));
|
||||
|
||||
if (HAS_PCH_NOP(dev))
|
||||
return;
|
||||
|
||||
I915_WRITE(SDEIMR, 0xffffffff);
|
||||
I915_WRITE(SDEIER, 0x0);
|
||||
I915_WRITE(SDEIIR, I915_READ(SDEIIR));
|
||||
|
@ -2607,13 +2711,16 @@ static irqreturn_t i915_irq_handler(int irq, void *arg)
|
|||
if ((I915_HAS_HOTPLUG(dev)) &&
|
||||
(iir & I915_DISPLAY_PORT_INTERRUPT)) {
|
||||
u32 hotplug_status = I915_READ(PORT_HOTPLUG_STAT);
|
||||
u32 hotplug_trigger = hotplug_status & HOTPLUG_INT_STATUS_I915;
|
||||
|
||||
DRM_DEBUG_DRIVER("hotplug event received, stat 0x%08x\n",
|
||||
hotplug_status);
|
||||
if (hotplug_status & HOTPLUG_INT_STATUS_I915)
|
||||
if (hotplug_trigger) {
|
||||
if (hotplug_irq_storm_detect(dev, hotplug_trigger, hpd_status_i915))
|
||||
i915_hpd_irq_setup(dev);
|
||||
queue_work(dev_priv->wq,
|
||||
&dev_priv->hotplug_work);
|
||||
|
||||
}
|
||||
I915_WRITE(PORT_HOTPLUG_STAT, hotplug_status);
|
||||
POSTING_READ(PORT_HOTPLUG_STAT);
|
||||
}
|
||||
|
@ -2669,6 +2776,8 @@ static void i915_irq_uninstall(struct drm_device * dev)
|
|||
drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private;
|
||||
int pipe;
|
||||
|
||||
del_timer_sync(&dev_priv->hotplug_reenable_timer);
|
||||
|
||||
if (I915_HAS_HOTPLUG(dev)) {
|
||||
I915_WRITE(PORT_HOTPLUG_EN, 0);
|
||||
I915_WRITE(PORT_HOTPLUG_STAT, I915_READ(PORT_HOTPLUG_STAT));
|
||||
|
@ -2760,7 +2869,7 @@ static void i915_hpd_irq_setup(struct drm_device *dev)
|
|||
{
|
||||
drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private;
|
||||
struct drm_mode_config *mode_config = &dev->mode_config;
|
||||
struct intel_encoder *encoder;
|
||||
struct intel_encoder *intel_encoder;
|
||||
u32 hotplug_en;
|
||||
|
||||
if (I915_HAS_HOTPLUG(dev)) {
|
||||
|
@ -2768,8 +2877,9 @@ static void i915_hpd_irq_setup(struct drm_device *dev)
|
|||
hotplug_en &= ~HOTPLUG_INT_EN_MASK;
|
||||
/* Note HDMI and DP share hotplug bits */
|
||||
/* enable bits are the same for all generations */
|
||||
list_for_each_entry(encoder, &mode_config->encoder_list, base.head)
|
||||
hotplug_en |= hpd_mask_i915[encoder->hpd_pin];
|
||||
list_for_each_entry(intel_encoder, &mode_config->encoder_list, base.head)
|
||||
if (dev_priv->hpd_stats[intel_encoder->hpd_pin].hpd_mark == HPD_ENABLED)
|
||||
hotplug_en |= hpd_mask_i915[intel_encoder->hpd_pin];
|
||||
/* Programming the CRT detection parameters tends
|
||||
to generate a spurious hotplug event about three
|
||||
seconds later. So just do it once.
|
||||
|
@ -2840,15 +2950,19 @@ static irqreturn_t i965_irq_handler(int irq, void *arg)
|
|||
/* Consume port. Then clear IIR or we'll miss events */
|
||||
if (iir & I915_DISPLAY_PORT_INTERRUPT) {
|
||||
u32 hotplug_status = I915_READ(PORT_HOTPLUG_STAT);
|
||||
u32 hotplug_trigger = hotplug_status & (IS_G4X(dev) ?
|
||||
HOTPLUG_INT_STATUS_G4X :
|
||||
HOTPLUG_INT_STATUS_I965);
|
||||
|
||||
DRM_DEBUG_DRIVER("hotplug event received, stat 0x%08x\n",
|
||||
hotplug_status);
|
||||
if (hotplug_status & (IS_G4X(dev) ?
|
||||
HOTPLUG_INT_STATUS_G4X :
|
||||
HOTPLUG_INT_STATUS_I965))
|
||||
if (hotplug_trigger) {
|
||||
if (hotplug_irq_storm_detect(dev, hotplug_trigger,
|
||||
IS_G4X(dev) ? hpd_status_gen4 : hpd_status_i965))
|
||||
i915_hpd_irq_setup(dev);
|
||||
queue_work(dev_priv->wq,
|
||||
&dev_priv->hotplug_work);
|
||||
|
||||
}
|
||||
I915_WRITE(PORT_HOTPLUG_STAT, hotplug_status);
|
||||
I915_READ(PORT_HOTPLUG_STAT);
|
||||
}
|
||||
|
@ -2908,6 +3022,8 @@ static void i965_irq_uninstall(struct drm_device * dev)
|
|||
if (!dev_priv)
|
||||
return;
|
||||
|
||||
del_timer_sync(&dev_priv->hotplug_reenable_timer);
|
||||
|
||||
I915_WRITE(PORT_HOTPLUG_EN, 0);
|
||||
I915_WRITE(PORT_HOTPLUG_STAT, I915_READ(PORT_HOTPLUG_STAT));
|
||||
|
||||
|
@ -2923,6 +3039,41 @@ static void i965_irq_uninstall(struct drm_device * dev)
|
|||
I915_WRITE(IIR, I915_READ(IIR));
|
||||
}
|
||||
|
||||
static void i915_reenable_hotplug_timer_func(unsigned long data)
|
||||
{
|
||||
drm_i915_private_t *dev_priv = (drm_i915_private_t *)data;
|
||||
struct drm_device *dev = dev_priv->dev;
|
||||
struct drm_mode_config *mode_config = &dev->mode_config;
|
||||
unsigned long irqflags;
|
||||
int i;
|
||||
|
||||
spin_lock_irqsave(&dev_priv->irq_lock, irqflags);
|
||||
for (i = (HPD_NONE + 1); i < HPD_NUM_PINS; i++) {
|
||||
struct drm_connector *connector;
|
||||
|
||||
if (dev_priv->hpd_stats[i].hpd_mark != HPD_DISABLED)
|
||||
continue;
|
||||
|
||||
dev_priv->hpd_stats[i].hpd_mark = HPD_ENABLED;
|
||||
|
||||
list_for_each_entry(connector, &mode_config->connector_list, head) {
|
||||
struct intel_connector *intel_connector = to_intel_connector(connector);
|
||||
|
||||
if (intel_connector->encoder->hpd_pin == i) {
|
||||
if (connector->polled != intel_connector->polled)
|
||||
DRM_DEBUG_DRIVER("Reenabling HPD on connector %s\n",
|
||||
drm_get_connector_name(connector));
|
||||
connector->polled = intel_connector->polled;
|
||||
if (!connector->polled)
|
||||
connector->polled = DRM_CONNECTOR_POLL_HPD;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (dev_priv->display.hpd_irq_setup)
|
||||
dev_priv->display.hpd_irq_setup(dev);
|
||||
spin_unlock_irqrestore(&dev_priv->irq_lock, irqflags);
|
||||
}
|
||||
|
||||
void intel_irq_init(struct drm_device *dev)
|
||||
{
|
||||
struct drm_i915_private *dev_priv = dev->dev_private;
|
||||
|
@ -2935,6 +3086,8 @@ void intel_irq_init(struct drm_device *dev)
|
|||
setup_timer(&dev_priv->gpu_error.hangcheck_timer,
|
||||
i915_hangcheck_elapsed,
|
||||
(unsigned long) dev);
|
||||
setup_timer(&dev_priv->hotplug_reenable_timer, i915_reenable_hotplug_timer_func,
|
||||
(unsigned long) dev_priv);
|
||||
|
||||
pm_qos_add_request(&dev_priv->pm_qos, PM_QOS_CPU_DMA_LATENCY, PM_QOS_DEFAULT_VALUE);
|
||||
|
||||
|
@ -3003,7 +3156,20 @@ void intel_irq_init(struct drm_device *dev)
|
|||
void intel_hpd_init(struct drm_device *dev)
|
||||
{
|
||||
struct drm_i915_private *dev_priv = dev->dev_private;
|
||||
struct drm_mode_config *mode_config = &dev->mode_config;
|
||||
struct drm_connector *connector;
|
||||
int i;
|
||||
|
||||
for (i = 1; i < HPD_NUM_PINS; i++) {
|
||||
dev_priv->hpd_stats[i].hpd_cnt = 0;
|
||||
dev_priv->hpd_stats[i].hpd_mark = HPD_ENABLED;
|
||||
}
|
||||
list_for_each_entry(connector, &mode_config->connector_list, head) {
|
||||
struct intel_connector *intel_connector = to_intel_connector(connector);
|
||||
connector->polled = intel_connector->polled;
|
||||
if (!connector->polled && I915_HAS_HOTPLUG(dev) && intel_connector->encoder->hpd_pin > HPD_NONE)
|
||||
connector->polled = DRM_CONNECTOR_POLL_HPD;
|
||||
}
|
||||
if (dev_priv->display.hpd_irq_setup)
|
||||
dev_priv->display.hpd_irq_setup(dev);
|
||||
}
|
||||
|
|
|
@ -125,8 +125,14 @@
|
|||
#define HSW_ECOCHK_ARB_PRIO_SOL (1<<6)
|
||||
#define ECOCHK_PPGTT_CACHE64B (0x3<<3)
|
||||
#define ECOCHK_PPGTT_CACHE4B (0x0<<3)
|
||||
#define ECOCHK_PPGTT_GFDT_IVB (0x1<<4)
|
||||
#define ECOCHK_PPGTT_LLC_IVB (0x1<<3)
|
||||
#define ECOCHK_PPGTT_UC_HSW (0x1<<3)
|
||||
#define ECOCHK_PPGTT_WT_HSW (0x2<<3)
|
||||
#define ECOCHK_PPGTT_WB_HSW (0x3<<3)
|
||||
|
||||
#define GAC_ECO_BITS 0x14090
|
||||
#define ECOBITS_SNB_BIT (1<<13)
|
||||
#define ECOBITS_PPGTT_CACHE64B (3<<8)
|
||||
#define ECOBITS_PPGTT_CACHE4B (0<<8)
|
||||
|
||||
|
@ -424,6 +430,7 @@
|
|||
|
||||
#define FENCE_REG_SANDYBRIDGE_0 0x100000
|
||||
#define SANDYBRIDGE_FENCE_PITCH_SHIFT 32
|
||||
#define GEN7_FENCE_MAX_PITCH_VAL 0x0800
|
||||
|
||||
/* control register for cpu gtt access */
|
||||
#define TILECTL 0x101000
|
||||
|
@ -1203,6 +1210,9 @@
|
|||
|
||||
#define MCHBAR_MIRROR_BASE_SNB 0x140000
|
||||
|
||||
/* Memory controller frequency in MCHBAR for Haswell (possible SNB+) */
|
||||
#define DCLK 0x5e04
|
||||
|
||||
/** 915-945 and GM965 MCH register controlling DRAM channel access */
|
||||
#define DCC 0x10200
|
||||
#define DCC_ADDRESSING_MODE_SINGLE_CHANNEL (0 << 0)
|
||||
|
@ -3568,6 +3578,9 @@
|
|||
#define DISP_ARB_CTL 0x45000
|
||||
#define DISP_TILE_SURFACE_SWIZZLING (1<<13)
|
||||
#define DISP_FBC_WM_DIS (1<<15)
|
||||
#define GEN7_MSG_CTL 0x45010
|
||||
#define WAIT_FOR_PCH_RESET_ACK (1<<1)
|
||||
#define WAIT_FOR_PCH_FLR_ACK (1<<0)
|
||||
|
||||
/* GEN7 chicken */
|
||||
#define GEN7_COMMON_SLICE_CHICKEN1 0x7010
|
||||
|
@ -3946,8 +3959,11 @@
|
|||
#define _TRANSA_CHICKEN2 0xf0064
|
||||
#define _TRANSB_CHICKEN2 0xf1064
|
||||
#define TRANS_CHICKEN2(pipe) _PIPE(pipe, _TRANSA_CHICKEN2, _TRANSB_CHICKEN2)
|
||||
#define TRANS_CHICKEN2_TIMING_OVERRIDE (1<<31)
|
||||
|
||||
#define TRANS_CHICKEN2_TIMING_OVERRIDE (1<<31)
|
||||
#define TRANS_CHICKEN2_FDI_POLARITY_REVERSED (1<<29)
|
||||
#define TRANS_CHICKEN2_FRAME_START_DELAY_MASK (3<<27)
|
||||
#define TRANS_CHICKEN2_DISABLE_DEEP_COLOR_COUNTER (1<<26)
|
||||
#define TRANS_CHICKEN2_DISABLE_DEEP_COLOR_MODESWITCH (1<<25)
|
||||
|
||||
#define SOUTH_CHICKEN1 0xc2000
|
||||
#define FDIA_PHASE_SYNC_SHIFT_OVR 19
|
||||
|
@ -4380,6 +4396,7 @@
|
|||
#define GEN6_DECODE_RC6_VID(vids) (((vids) * 5) + 245)
|
||||
#define GEN6_PCODE_DATA 0x138128
|
||||
#define GEN6_PCODE_FREQ_IA_RATIO_SHIFT 8
|
||||
#define GEN6_PCODE_FREQ_RING_RATIO_SHIFT 16
|
||||
|
||||
#define VLV_IOSF_DOORBELL_REQ 0x182100
|
||||
#define IOSF_DEVFN_SHIFT 24
|
||||
|
|
|
@ -239,7 +239,7 @@ static ssize_t gt_max_freq_mhz_store(struct device *kdev,
|
|||
struct drm_minor *minor = container_of(kdev, struct drm_minor, kdev);
|
||||
struct drm_device *dev = minor->dev;
|
||||
struct drm_i915_private *dev_priv = dev->dev_private;
|
||||
u32 val, rp_state_cap, hw_max, hw_min;
|
||||
u32 val, rp_state_cap, hw_max, hw_min, non_oc_max;
|
||||
ssize_t ret;
|
||||
|
||||
ret = kstrtou32(buf, 0, &val);
|
||||
|
@ -251,7 +251,8 @@ static ssize_t gt_max_freq_mhz_store(struct device *kdev,
|
|||
mutex_lock(&dev_priv->rps.hw_lock);
|
||||
|
||||
rp_state_cap = I915_READ(GEN6_RP_STATE_CAP);
|
||||
hw_max = (rp_state_cap & 0xff);
|
||||
hw_max = dev_priv->rps.hw_max;
|
||||
non_oc_max = (rp_state_cap & 0xff);
|
||||
hw_min = ((rp_state_cap & 0xff0000) >> 16);
|
||||
|
||||
if (val < hw_min || val > hw_max || val < dev_priv->rps.min_delay) {
|
||||
|
@ -259,6 +260,10 @@ static ssize_t gt_max_freq_mhz_store(struct device *kdev,
|
|||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (val > non_oc_max)
|
||||
DRM_DEBUG("User requested overclocking to %d\n",
|
||||
val * GT_FREQUENCY_MULTIPLIER);
|
||||
|
||||
if (dev_priv->rps.cur_delay > val)
|
||||
gen6_set_rps(dev_priv->dev, val);
|
||||
|
||||
|
@ -302,7 +307,7 @@ static ssize_t gt_min_freq_mhz_store(struct device *kdev,
|
|||
mutex_lock(&dev_priv->rps.hw_lock);
|
||||
|
||||
rp_state_cap = I915_READ(GEN6_RP_STATE_CAP);
|
||||
hw_max = (rp_state_cap & 0xff);
|
||||
hw_max = dev_priv->rps.hw_max;
|
||||
hw_min = ((rp_state_cap & 0xff0000) >> 16);
|
||||
|
||||
if (val < hw_min || val > hw_max || val > dev_priv->rps.max_delay) {
|
||||
|
|
|
@ -351,12 +351,14 @@ parse_general_features(struct drm_i915_private *dev_priv,
|
|||
dev_priv->lvds_ssc_freq =
|
||||
intel_bios_ssc_frequency(dev, general->ssc_freq);
|
||||
dev_priv->display_clock_mode = general->display_clock_mode;
|
||||
DRM_DEBUG_KMS("BDB_GENERAL_FEATURES int_tv_support %d int_crt_support %d lvds_use_ssc %d lvds_ssc_freq %d display_clock_mode %d\n",
|
||||
dev_priv->fdi_rx_polarity_inverted = general->fdi_rx_polarity_inverted;
|
||||
DRM_DEBUG_KMS("BDB_GENERAL_FEATURES int_tv_support %d int_crt_support %d lvds_use_ssc %d lvds_ssc_freq %d display_clock_mode %d fdi_rx_polarity_inverted %d\n",
|
||||
dev_priv->int_tv_support,
|
||||
dev_priv->int_crt_support,
|
||||
dev_priv->lvds_use_ssc,
|
||||
dev_priv->lvds_ssc_freq,
|
||||
dev_priv->display_clock_mode);
|
||||
dev_priv->display_clock_mode,
|
||||
dev_priv->fdi_rx_polarity_inverted);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -692,6 +694,9 @@ intel_parse_bios(struct drm_device *dev)
|
|||
struct bdb_header *bdb = NULL;
|
||||
u8 __iomem *bios = NULL;
|
||||
|
||||
if (HAS_PCH_NOP(dev))
|
||||
return -ENODEV;
|
||||
|
||||
init_vbt_defaults(dev_priv);
|
||||
|
||||
/* XXX Should this validation be moved to intel_opregion.c? */
|
||||
|
|
|
@ -127,7 +127,9 @@ struct bdb_general_features {
|
|||
/* bits 3 */
|
||||
u8 disable_smooth_vision:1;
|
||||
u8 single_dvi:1;
|
||||
u8 rsvd9:6; /* finish byte */
|
||||
u8 rsvd9:1;
|
||||
u8 fdi_rx_polarity_inverted:1;
|
||||
u8 rsvd10:4; /* finish byte */
|
||||
|
||||
/* bits 4 */
|
||||
u8 legacy_monitor_detect;
|
||||
|
|
|
@ -787,10 +787,8 @@ void intel_crt_init(struct drm_device *dev)
|
|||
|
||||
drm_sysfs_connector_add(connector);
|
||||
|
||||
if (I915_HAS_HOTPLUG(dev))
|
||||
connector->polled = DRM_CONNECTOR_POLL_HPD;
|
||||
else
|
||||
connector->polled = DRM_CONNECTOR_POLL_CONNECT;
|
||||
if (!I915_HAS_HOTPLUG(dev))
|
||||
intel_connector->polled = DRM_CONNECTOR_POLL_CONNECT;
|
||||
|
||||
/*
|
||||
* Configure the automatic hotplug detection stuff
|
||||
|
|
|
@ -924,7 +924,7 @@ void intel_ddi_set_pipe_settings(struct drm_crtc *crtc)
|
|||
struct drm_i915_private *dev_priv = crtc->dev->dev_private;
|
||||
struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
|
||||
struct intel_encoder *intel_encoder = intel_ddi_get_crtc_encoder(crtc);
|
||||
enum transcoder cpu_transcoder = intel_crtc->cpu_transcoder;
|
||||
enum transcoder cpu_transcoder = intel_crtc->config.cpu_transcoder;
|
||||
int type = intel_encoder->type;
|
||||
uint32_t temp;
|
||||
|
||||
|
@ -958,7 +958,7 @@ void intel_ddi_enable_transcoder_func(struct drm_crtc *crtc)
|
|||
struct drm_encoder *encoder = &intel_encoder->base;
|
||||
struct drm_i915_private *dev_priv = crtc->dev->dev_private;
|
||||
enum pipe pipe = intel_crtc->pipe;
|
||||
enum transcoder cpu_transcoder = intel_crtc->cpu_transcoder;
|
||||
enum transcoder cpu_transcoder = intel_crtc->config.cpu_transcoder;
|
||||
enum port port = intel_ddi_get_encoder_port(intel_encoder);
|
||||
int type = intel_encoder->type;
|
||||
uint32_t temp;
|
||||
|
@ -1223,7 +1223,7 @@ void intel_ddi_enable_pipe_clock(struct intel_crtc *intel_crtc)
|
|||
struct drm_i915_private *dev_priv = crtc->dev->dev_private;
|
||||
struct intel_encoder *intel_encoder = intel_ddi_get_crtc_encoder(crtc);
|
||||
enum port port = intel_ddi_get_encoder_port(intel_encoder);
|
||||
enum transcoder cpu_transcoder = intel_crtc->cpu_transcoder;
|
||||
enum transcoder cpu_transcoder = intel_crtc->config.cpu_transcoder;
|
||||
|
||||
if (cpu_transcoder != TRANSCODER_EDP)
|
||||
I915_WRITE(TRANS_CLK_SEL(cpu_transcoder),
|
||||
|
@ -1233,7 +1233,7 @@ void intel_ddi_enable_pipe_clock(struct intel_crtc *intel_crtc)
|
|||
void intel_ddi_disable_pipe_clock(struct intel_crtc *intel_crtc)
|
||||
{
|
||||
struct drm_i915_private *dev_priv = intel_crtc->base.dev->dev_private;
|
||||
enum transcoder cpu_transcoder = intel_crtc->cpu_transcoder;
|
||||
enum transcoder cpu_transcoder = intel_crtc->config.cpu_transcoder;
|
||||
|
||||
if (cpu_transcoder != TRANSCODER_EDP)
|
||||
I915_WRITE(TRANS_CLK_SEL(cpu_transcoder),
|
||||
|
|
|
@ -892,7 +892,7 @@ enum transcoder intel_pipe_to_cpu_transcoder(struct drm_i915_private *dev_priv,
|
|||
struct drm_crtc *crtc = dev_priv->pipe_to_crtc_mapping[pipe];
|
||||
struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
|
||||
|
||||
return intel_crtc->cpu_transcoder;
|
||||
return intel_crtc->config.cpu_transcoder;
|
||||
}
|
||||
|
||||
static void ironlake_wait_for_vblank(struct drm_device *dev, int pipe)
|
||||
|
@ -1227,8 +1227,8 @@ void assert_pipe(struct drm_i915_private *dev_priv,
|
|||
if (pipe == PIPE_A && dev_priv->quirks & QUIRK_PIPEA_FORCE)
|
||||
state = true;
|
||||
|
||||
if (IS_HASWELL(dev_priv->dev) && cpu_transcoder != TRANSCODER_EDP &&
|
||||
!(I915_READ(HSW_PWR_WELL_DRIVER) & HSW_PWR_WELL_ENABLE)) {
|
||||
if (!intel_using_power_well(dev_priv->dev) &&
|
||||
cpu_transcoder != TRANSCODER_EDP) {
|
||||
cur_state = false;
|
||||
} else {
|
||||
reg = PIPECONF(cpu_transcoder);
|
||||
|
@ -2002,8 +2002,10 @@ intel_pin_and_fence_fb_obj(struct drm_device *dev,
|
|||
alignment = 0;
|
||||
break;
|
||||
case I915_TILING_Y:
|
||||
/* FIXME: Is this true? */
|
||||
DRM_ERROR("Y tiled not allowed for scan out buffers\n");
|
||||
/* Despite that we check this in framebuffer_init userspace can
|
||||
* screw us over and change the tiling after the fact. Only
|
||||
* pinned buffers can't change their tiling. */
|
||||
DRM_DEBUG_DRIVER("Y tiled not allowed for scan out buffers\n");
|
||||
return -EINVAL;
|
||||
default:
|
||||
BUG();
|
||||
|
@ -3201,7 +3203,7 @@ static void lpt_pch_enable(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);
|
||||
enum transcoder cpu_transcoder = intel_crtc->cpu_transcoder;
|
||||
enum transcoder cpu_transcoder = intel_crtc->config.cpu_transcoder;
|
||||
|
||||
assert_transcoder_disabled(dev_priv, TRANSCODER_A);
|
||||
|
||||
|
@ -3576,7 +3578,7 @@ static void haswell_crtc_disable(struct drm_crtc *crtc)
|
|||
struct intel_encoder *encoder;
|
||||
int pipe = intel_crtc->pipe;
|
||||
int plane = intel_crtc->plane;
|
||||
enum transcoder cpu_transcoder = intel_crtc->cpu_transcoder;
|
||||
enum transcoder cpu_transcoder = intel_crtc->config.cpu_transcoder;
|
||||
|
||||
if (!intel_crtc->active)
|
||||
return;
|
||||
|
@ -3597,9 +3599,13 @@ static void haswell_crtc_disable(struct drm_crtc *crtc)
|
|||
|
||||
intel_ddi_disable_transcoder_func(dev_priv, cpu_transcoder);
|
||||
|
||||
/* Disable PF */
|
||||
I915_WRITE(PF_CTL(pipe), 0);
|
||||
I915_WRITE(PF_WIN_SZ(pipe), 0);
|
||||
/* XXX: Once we have proper panel fitter state tracking implemented with
|
||||
* hardware state read/check support we should switch to only disable
|
||||
* the panel fitter when we know it's used. */
|
||||
if (intel_using_power_well(dev)) {
|
||||
I915_WRITE(PF_CTL(pipe), 0);
|
||||
I915_WRITE(PF_WIN_SZ(pipe), 0);
|
||||
}
|
||||
|
||||
intel_ddi_disable_pipe_clock(intel_crtc);
|
||||
|
||||
|
@ -3632,7 +3638,7 @@ static void haswell_crtc_off(struct drm_crtc *crtc)
|
|||
|
||||
/* Stop saying we're using TRANSCODER_EDP because some other CRTC might
|
||||
* start using it. */
|
||||
intel_crtc->cpu_transcoder = (enum transcoder) intel_crtc->pipe;
|
||||
intel_crtc->config.cpu_transcoder = (enum transcoder) intel_crtc->pipe;
|
||||
|
||||
intel_ddi_put_crtc_pll(crtc);
|
||||
}
|
||||
|
@ -3718,6 +3724,26 @@ static void i9xx_crtc_enable(struct drm_crtc *crtc)
|
|||
encoder->enable(encoder);
|
||||
}
|
||||
|
||||
static void i9xx_pfit_disable(struct intel_crtc *crtc)
|
||||
{
|
||||
struct drm_device *dev = crtc->base.dev;
|
||||
struct drm_i915_private *dev_priv = dev->dev_private;
|
||||
enum pipe pipe;
|
||||
uint32_t pctl = I915_READ(PFIT_CONTROL);
|
||||
|
||||
assert_pipe_disabled(dev_priv, crtc->pipe);
|
||||
|
||||
if (INTEL_INFO(dev)->gen >= 4)
|
||||
pipe = (pctl & PFIT_PIPE_MASK) >> PFIT_PIPE_SHIFT;
|
||||
else
|
||||
pipe = PIPE_B;
|
||||
|
||||
if (pipe == crtc->pipe) {
|
||||
DRM_DEBUG_DRIVER("disabling pfit, current: 0x%08x\n", pctl);
|
||||
I915_WRITE(PFIT_CONTROL, 0);
|
||||
}
|
||||
}
|
||||
|
||||
static void i9xx_crtc_disable(struct drm_crtc *crtc)
|
||||
{
|
||||
struct drm_device *dev = crtc->dev;
|
||||
|
@ -3726,8 +3752,6 @@ static void i9xx_crtc_disable(struct drm_crtc *crtc)
|
|||
struct intel_encoder *encoder;
|
||||
int pipe = intel_crtc->pipe;
|
||||
int plane = intel_crtc->plane;
|
||||
u32 pctl;
|
||||
|
||||
|
||||
if (!intel_crtc->active)
|
||||
return;
|
||||
|
@ -3747,11 +3771,7 @@ static void i9xx_crtc_disable(struct drm_crtc *crtc)
|
|||
intel_disable_plane(dev_priv, plane, pipe);
|
||||
intel_disable_pipe(dev_priv, pipe);
|
||||
|
||||
/* Disable pannel fitter if it is on this pipe. */
|
||||
pctl = I915_READ(PFIT_CONTROL);
|
||||
if ((pctl & PFIT_ENABLE) &&
|
||||
((pctl & PFIT_PIPE_MASK) >> PFIT_PIPE_SHIFT) == pipe)
|
||||
I915_WRITE(PFIT_CONTROL, 0);
|
||||
i9xx_pfit_disable(intel_crtc);
|
||||
|
||||
intel_disable_pll(dev_priv, pipe);
|
||||
|
||||
|
@ -3983,9 +4003,9 @@ static bool intel_crtc_compute_config(struct drm_crtc *crtc,
|
|||
adjusted_mode->hsync_start == adjusted_mode->hdisplay)
|
||||
return false;
|
||||
|
||||
if ((IS_G4X(dev) || IS_VALLEYVIEW(dev)) && pipe_config->pipe_bpp > 10) {
|
||||
if ((IS_G4X(dev) || IS_VALLEYVIEW(dev)) && pipe_config->pipe_bpp > 10*3) {
|
||||
pipe_config->pipe_bpp = 10*3; /* 12bpc is gen5+ */
|
||||
} else if (INTEL_INFO(dev)->gen <= 4 && pipe_config->pipe_bpp > 8) {
|
||||
} else if (INTEL_INFO(dev)->gen <= 4 && pipe_config->pipe_bpp > 8*3) {
|
||||
/* only a 8bpc pipe, with 6bpc dither through the panel fitter
|
||||
* for lvds. */
|
||||
pipe_config->pipe_bpp = 8*3;
|
||||
|
@ -4474,7 +4494,7 @@ static void intel_set_pipe_timings(struct intel_crtc *intel_crtc,
|
|||
struct drm_device *dev = intel_crtc->base.dev;
|
||||
struct drm_i915_private *dev_priv = dev->dev_private;
|
||||
enum pipe pipe = intel_crtc->pipe;
|
||||
enum transcoder cpu_transcoder = intel_crtc->cpu_transcoder;
|
||||
enum transcoder cpu_transcoder = intel_crtc->config.cpu_transcoder;
|
||||
uint32_t vsyncshift;
|
||||
|
||||
if (!IS_GEN2(dev) && adjusted_mode->flags & DRM_MODE_FLAG_INTERLACE) {
|
||||
|
@ -4956,13 +4976,6 @@ static void lpt_init_pch_refclk(struct drm_device *dev)
|
|||
tmp |= (0x12 << 24);
|
||||
intel_sbi_write(dev_priv, 0x8008, tmp, SBI_MPHY);
|
||||
|
||||
if (!is_sdv) {
|
||||
tmp = intel_sbi_read(dev_priv, 0x808C, SBI_MPHY);
|
||||
tmp &= ~(0x3 << 6);
|
||||
tmp |= (1 << 6) | (1 << 0);
|
||||
intel_sbi_write(dev_priv, 0x808C, tmp, SBI_MPHY);
|
||||
}
|
||||
|
||||
if (is_sdv) {
|
||||
tmp = intel_sbi_read(dev_priv, 0x800C, SBI_MPHY);
|
||||
tmp |= 0x7FFF;
|
||||
|
@ -5223,7 +5236,7 @@ static void haswell_set_pipeconf(struct drm_crtc *crtc,
|
|||
{
|
||||
struct drm_i915_private *dev_priv = crtc->dev->dev_private;
|
||||
struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
|
||||
enum transcoder cpu_transcoder = intel_crtc->cpu_transcoder;
|
||||
enum transcoder cpu_transcoder = intel_crtc->config.cpu_transcoder;
|
||||
uint32_t val;
|
||||
|
||||
val = I915_READ(PIPECONF(cpu_transcoder));
|
||||
|
@ -5417,7 +5430,7 @@ void intel_cpu_transcoder_set_m_n(struct intel_crtc *crtc,
|
|||
struct drm_device *dev = crtc->base.dev;
|
||||
struct drm_i915_private *dev_priv = dev->dev_private;
|
||||
int pipe = crtc->pipe;
|
||||
enum transcoder transcoder = crtc->cpu_transcoder;
|
||||
enum transcoder transcoder = crtc->config.cpu_transcoder;
|
||||
|
||||
if (INTEL_INFO(dev)->gen >= 5) {
|
||||
I915_WRITE(PIPE_DATA_M1(transcoder), TU_SIZE(m_n->tu) | m_n->gmch_m);
|
||||
|
@ -5469,7 +5482,8 @@ static void ironlake_fdi_set_m_n(struct drm_crtc *crtc)
|
|||
}
|
||||
|
||||
static uint32_t ironlake_compute_dpll(struct intel_crtc *intel_crtc,
|
||||
intel_clock_t *clock, u32 fp)
|
||||
intel_clock_t *clock, u32 *fp,
|
||||
intel_clock_t *reduced_clock, u32 *fp2)
|
||||
{
|
||||
struct drm_crtc *crtc = &intel_crtc->base;
|
||||
struct drm_device *dev = crtc->dev;
|
||||
|
@ -5503,13 +5517,16 @@ static uint32_t ironlake_compute_dpll(struct intel_crtc *intel_crtc,
|
|||
if (is_lvds) {
|
||||
if ((intel_panel_use_ssc(dev_priv) &&
|
||||
dev_priv->lvds_ssc_freq == 100) ||
|
||||
intel_is_dual_link_lvds(dev))
|
||||
(HAS_PCH_IBX(dev) && intel_is_dual_link_lvds(dev)))
|
||||
factor = 25;
|
||||
} else if (is_sdvo && is_tv)
|
||||
factor = 20;
|
||||
|
||||
if (clock->m < factor * clock->n)
|
||||
fp |= FP_CB_TUNE;
|
||||
*fp |= FP_CB_TUNE;
|
||||
|
||||
if (fp2 && (reduced_clock->m < factor * reduced_clock->n))
|
||||
*fp2 |= FP_CB_TUNE;
|
||||
|
||||
dpll = 0;
|
||||
|
||||
|
@ -5596,7 +5613,7 @@ static int ironlake_crtc_mode_set(struct drm_crtc *crtc,
|
|||
WARN(!(HAS_PCH_IBX(dev) || HAS_PCH_CPT(dev)),
|
||||
"Unexpected PCH type %d\n", INTEL_PCH_TYPE(dev));
|
||||
|
||||
intel_crtc->cpu_transcoder = pipe;
|
||||
intel_crtc->config.cpu_transcoder = pipe;
|
||||
|
||||
ok = ironlake_compute_clocks(crtc, adjusted_mode, &clock,
|
||||
&has_reduced_clock, &reduced_clock);
|
||||
|
@ -5626,7 +5643,8 @@ static int ironlake_crtc_mode_set(struct drm_crtc *crtc,
|
|||
fp2 = reduced_clock.n << 16 | reduced_clock.m1 << 8 |
|
||||
reduced_clock.m2;
|
||||
|
||||
dpll = ironlake_compute_dpll(intel_crtc, &clock, fp);
|
||||
dpll = ironlake_compute_dpll(intel_crtc, &clock, &fp, &reduced_clock,
|
||||
has_reduced_clock ? &fp2 : NULL);
|
||||
|
||||
DRM_DEBUG_KMS("Mode for pipe %d:\n", pipe);
|
||||
drm_mode_debug_printmodeline(mode);
|
||||
|
@ -5779,9 +5797,9 @@ static int haswell_crtc_mode_set(struct drm_crtc *crtc,
|
|||
}
|
||||
|
||||
if (is_cpu_edp)
|
||||
intel_crtc->cpu_transcoder = TRANSCODER_EDP;
|
||||
intel_crtc->config.cpu_transcoder = TRANSCODER_EDP;
|
||||
else
|
||||
intel_crtc->cpu_transcoder = pipe;
|
||||
intel_crtc->config.cpu_transcoder = pipe;
|
||||
|
||||
/* We are not sure yet this won't happen. */
|
||||
WARN(!HAS_PCH_LPT(dev), "Unexpected PCH type %d\n",
|
||||
|
@ -5790,7 +5808,7 @@ static int haswell_crtc_mode_set(struct drm_crtc *crtc,
|
|||
WARN(num_connectors != 1, "%d connectors attached to pipe %c\n",
|
||||
num_connectors, pipe_name(pipe));
|
||||
|
||||
WARN_ON(I915_READ(PIPECONF(intel_crtc->cpu_transcoder)) &
|
||||
WARN_ON(I915_READ(PIPECONF(intel_crtc->config.cpu_transcoder)) &
|
||||
(PIPECONF_ENABLE | I965_PIPECONF_ACTIVE));
|
||||
|
||||
WARN_ON(I915_READ(DSPCNTR(plane)) & DISPLAY_PLANE_ENABLE);
|
||||
|
@ -5841,7 +5859,7 @@ static bool haswell_get_pipe_config(struct intel_crtc *crtc,
|
|||
struct drm_i915_private *dev_priv = dev->dev_private;
|
||||
uint32_t tmp;
|
||||
|
||||
tmp = I915_READ(PIPECONF(crtc->cpu_transcoder));
|
||||
tmp = I915_READ(PIPECONF(crtc->config.cpu_transcoder));
|
||||
if (!(tmp & PIPECONF_ENABLE))
|
||||
return false;
|
||||
|
||||
|
@ -6809,7 +6827,7 @@ struct drm_display_mode *intel_crtc_mode_get(struct drm_device *dev,
|
|||
{
|
||||
struct drm_i915_private *dev_priv = dev->dev_private;
|
||||
struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
|
||||
enum transcoder cpu_transcoder = intel_crtc->cpu_transcoder;
|
||||
enum transcoder cpu_transcoder = intel_crtc->config.cpu_transcoder;
|
||||
struct drm_display_mode *mode;
|
||||
int htot = I915_READ(HTOTAL(cpu_transcoder));
|
||||
int hsync = I915_READ(HSYNC(cpu_transcoder));
|
||||
|
@ -7708,22 +7726,25 @@ intel_modeset_affected_pipes(struct drm_crtc *crtc, unsigned *modeset_pipes,
|
|||
if (crtc->enabled)
|
||||
*prepare_pipes |= 1 << intel_crtc->pipe;
|
||||
|
||||
/* We only support modeset on one single crtc, hence we need to do that
|
||||
* only for the passed in crtc iff we change anything else than just
|
||||
* disable crtcs.
|
||||
*
|
||||
* This is actually not true, to be fully compatible with the old crtc
|
||||
* helper we automatically disable _any_ output (i.e. doesn't need to be
|
||||
* connected to the crtc we're modesetting on) if it's disconnected.
|
||||
* Which is a rather nutty api (since changed the output configuration
|
||||
* without userspace's explicit request can lead to confusion), but
|
||||
* alas. Hence we currently need to modeset on all pipes we prepare. */
|
||||
/*
|
||||
* For simplicity do a full modeset on any pipe where the output routing
|
||||
* changed. We could be more clever, but that would require us to be
|
||||
* more careful with calling the relevant encoder->mode_set functions.
|
||||
*/
|
||||
if (*prepare_pipes)
|
||||
*modeset_pipes = *prepare_pipes;
|
||||
|
||||
/* ... and mask these out. */
|
||||
*modeset_pipes &= ~(*disable_pipes);
|
||||
*prepare_pipes &= ~(*disable_pipes);
|
||||
|
||||
/*
|
||||
* HACK: We don't (yet) fully support global modesets. intel_set_config
|
||||
* obies this rule, but the modeset restore mode of
|
||||
* intel_modeset_setup_hw_state does not.
|
||||
*/
|
||||
*modeset_pipes &= 1 << intel_crtc->pipe;
|
||||
*prepare_pipes &= 1 << intel_crtc->pipe;
|
||||
}
|
||||
|
||||
static bool intel_crtc_in_use(struct drm_crtc *crtc)
|
||||
|
@ -7916,9 +7937,9 @@ intel_modeset_check_state(struct drm_device *dev)
|
|||
}
|
||||
}
|
||||
|
||||
int intel_set_mode(struct drm_crtc *crtc,
|
||||
struct drm_display_mode *mode,
|
||||
int x, int y, struct drm_framebuffer *fb)
|
||||
static int __intel_set_mode(struct drm_crtc *crtc,
|
||||
struct drm_display_mode *mode,
|
||||
int x, int y, struct drm_framebuffer *fb)
|
||||
{
|
||||
struct drm_device *dev = crtc->dev;
|
||||
drm_i915_private_t *dev_priv = dev->dev_private;
|
||||
|
@ -7969,10 +7990,12 @@ int intel_set_mode(struct drm_crtc *crtc,
|
|||
* to set it here already despite that we pass it down the callchain.
|
||||
*/
|
||||
if (modeset_pipes) {
|
||||
enum transcoder tmp = to_intel_crtc(crtc)->config.cpu_transcoder;
|
||||
crtc->mode = *mode;
|
||||
/* mode_set/enable/disable functions rely on a correct pipe
|
||||
* config. */
|
||||
to_intel_crtc(crtc)->config = *pipe_config;
|
||||
to_intel_crtc(crtc)->config.cpu_transcoder = tmp;
|
||||
}
|
||||
|
||||
/* Only after disabling all output pipelines that will be changed can we
|
||||
|
@ -8012,8 +8035,6 @@ done:
|
|||
if (ret && crtc->enabled) {
|
||||
crtc->hwmode = *saved_hwmode;
|
||||
crtc->mode = *saved_mode;
|
||||
} else {
|
||||
intel_modeset_check_state(dev);
|
||||
}
|
||||
|
||||
out:
|
||||
|
@ -8022,6 +8043,20 @@ out:
|
|||
return ret;
|
||||
}
|
||||
|
||||
int intel_set_mode(struct drm_crtc *crtc,
|
||||
struct drm_display_mode *mode,
|
||||
int x, int y, struct drm_framebuffer *fb)
|
||||
{
|
||||
int ret;
|
||||
|
||||
ret = __intel_set_mode(crtc, mode, x, y, fb);
|
||||
|
||||
if (ret == 0)
|
||||
intel_modeset_check_state(crtc->dev);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
void intel_crtc_restore_mode(struct drm_crtc *crtc)
|
||||
{
|
||||
intel_set_mode(crtc, &crtc->mode, crtc->x, crtc->y, crtc->fb);
|
||||
|
@ -8371,7 +8406,7 @@ static void intel_crtc_init(struct drm_device *dev, int pipe)
|
|||
/* Swap pipes & planes for FBC on pre-965 */
|
||||
intel_crtc->pipe = pipe;
|
||||
intel_crtc->plane = pipe;
|
||||
intel_crtc->cpu_transcoder = pipe;
|
||||
intel_crtc->config.cpu_transcoder = pipe;
|
||||
if (IS_MOBILE(dev) && IS_GEN3(dev)) {
|
||||
DRM_DEBUG_KMS("swapping pipes & planes for FBC\n");
|
||||
intel_crtc->plane = !pipe;
|
||||
|
@ -8462,7 +8497,7 @@ static void intel_setup_outputs(struct drm_device *dev)
|
|||
I915_WRITE(PFIT_CONTROL, 0);
|
||||
}
|
||||
|
||||
if (!(HAS_DDI(dev) && (I915_READ(DDI_BUF_CTL(PORT_A)) & DDI_A_4_LANES)))
|
||||
if (!IS_ULT(dev))
|
||||
intel_crt_init(dev);
|
||||
|
||||
if (HAS_DDI(dev)) {
|
||||
|
@ -8991,6 +9026,9 @@ void intel_modeset_init(struct drm_device *dev)
|
|||
|
||||
intel_init_pm(dev);
|
||||
|
||||
if (INTEL_INFO(dev)->num_pipes == 0)
|
||||
return;
|
||||
|
||||
intel_init_display(dev);
|
||||
|
||||
if (IS_GEN2(dev)) {
|
||||
|
@ -9093,7 +9131,7 @@ static void intel_sanitize_crtc(struct intel_crtc *crtc)
|
|||
u32 reg;
|
||||
|
||||
/* Clear any frame start delays used for debugging left by the BIOS */
|
||||
reg = PIPECONF(crtc->cpu_transcoder);
|
||||
reg = PIPECONF(crtc->config.cpu_transcoder);
|
||||
I915_WRITE(reg, I915_READ(reg) & ~PIPECONF_FRAME_START_DELAY_MASK);
|
||||
|
||||
/* We need to sanitize the plane -> pipe mapping first because this will
|
||||
|
@ -9259,7 +9297,7 @@ void intel_modeset_setup_hw_state(struct drm_device *dev,
|
|||
}
|
||||
|
||||
crtc = to_intel_crtc(dev_priv->pipe_to_crtc_mapping[pipe]);
|
||||
crtc->cpu_transcoder = TRANSCODER_EDP;
|
||||
crtc->config.cpu_transcoder = TRANSCODER_EDP;
|
||||
|
||||
DRM_DEBUG_KMS("Pipe %c using transcoder EDP\n",
|
||||
pipe_name(pipe));
|
||||
|
@ -9269,7 +9307,10 @@ void intel_modeset_setup_hw_state(struct drm_device *dev,
|
|||
setup_pipes:
|
||||
list_for_each_entry(crtc, &dev->mode_config.crtc_list,
|
||||
base.head) {
|
||||
enum transcoder tmp = crtc->config.cpu_transcoder;
|
||||
memset(&crtc->config, 0, sizeof(crtc->config));
|
||||
crtc->config.cpu_transcoder = tmp;
|
||||
|
||||
crtc->active = dev_priv->display.get_pipe_config(crtc,
|
||||
&crtc->config);
|
||||
|
||||
|
@ -9330,10 +9371,16 @@ setup_pipes:
|
|||
}
|
||||
|
||||
if (force_restore) {
|
||||
/*
|
||||
* We need to use raw interfaces for restoring state to avoid
|
||||
* checking (bogus) intermediate states.
|
||||
*/
|
||||
for_each_pipe(pipe) {
|
||||
struct drm_crtc *crtc =
|
||||
dev_priv->pipe_to_crtc_mapping[pipe];
|
||||
intel_crtc_restore_mode(crtc);
|
||||
|
||||
__intel_set_mode(crtc, &crtc->mode, crtc->x, crtc->y,
|
||||
crtc->fb);
|
||||
}
|
||||
list_for_each_entry(plane, &dev->mode_config.plane_list, head)
|
||||
intel_plane_restore(plane);
|
||||
|
@ -9398,6 +9445,9 @@ void intel_modeset_cleanup(struct drm_device *dev)
|
|||
/* flush any delayed tasks or pending work */
|
||||
flush_scheduled_work();
|
||||
|
||||
/* destroy backlight, if any, before the connectors */
|
||||
intel_panel_destroy_backlight(dev);
|
||||
|
||||
drm_mode_config_cleanup(dev);
|
||||
|
||||
intel_cleanup_overlay(dev);
|
||||
|
|
|
@ -353,10 +353,14 @@ intel_dp_aux_ch(struct intel_dp *intel_dp,
|
|||
aux_clock_divider = 200; /* SNB & IVB eDP input clock at 400Mhz */
|
||||
else
|
||||
aux_clock_divider = 225; /* eDP input clock at 450Mhz */
|
||||
} else if (HAS_PCH_SPLIT(dev))
|
||||
} else if (dev_priv->pch_id == INTEL_PCH_LPT_DEVICE_ID_TYPE) {
|
||||
/* Workaround for non-ULT HSW */
|
||||
aux_clock_divider = 74;
|
||||
} else if (HAS_PCH_SPLIT(dev)) {
|
||||
aux_clock_divider = DIV_ROUND_UP(intel_pch_rawclk(dev), 2);
|
||||
else
|
||||
} else {
|
||||
aux_clock_divider = intel_hrawclk(dev) / 2;
|
||||
}
|
||||
|
||||
if (IS_GEN6(dev))
|
||||
precharge = 3;
|
||||
|
@ -2470,17 +2474,14 @@ done:
|
|||
static void
|
||||
intel_dp_destroy(struct drm_connector *connector)
|
||||
{
|
||||
struct drm_device *dev = connector->dev;
|
||||
struct intel_dp *intel_dp = intel_attached_dp(connector);
|
||||
struct intel_connector *intel_connector = to_intel_connector(connector);
|
||||
|
||||
if (!IS_ERR_OR_NULL(intel_connector->edid))
|
||||
kfree(intel_connector->edid);
|
||||
|
||||
if (is_edp(intel_dp)) {
|
||||
intel_panel_destroy_backlight(dev);
|
||||
if (is_edp(intel_dp))
|
||||
intel_panel_fini(&intel_connector->panel);
|
||||
}
|
||||
|
||||
drm_sysfs_connector_remove(connector);
|
||||
drm_connector_cleanup(connector);
|
||||
|
@ -2789,7 +2790,6 @@ intel_dp_init_connector(struct intel_digital_port *intel_dig_port,
|
|||
drm_connector_init(dev, connector, &intel_dp_connector_funcs, type);
|
||||
drm_connector_helper_add(connector, &intel_dp_connector_helper_funcs);
|
||||
|
||||
connector->polled = DRM_CONNECTOR_POLL_HPD;
|
||||
connector->interlace_allowed = true;
|
||||
connector->doublescan_allowed = 0;
|
||||
|
||||
|
|
|
@ -171,6 +171,10 @@ struct intel_connector {
|
|||
|
||||
/* Cached EDID for eDP and LVDS. May hold ERR_PTR for invalid EDID. */
|
||||
struct edid *edid;
|
||||
|
||||
/* since POLL and HPD connectors may use the same HPD line keep the native
|
||||
state of connector->polled in case hotplug storm detection changes it */
|
||||
u8 polled;
|
||||
};
|
||||
|
||||
struct intel_crtc_config {
|
||||
|
@ -184,6 +188,10 @@ struct intel_crtc_config {
|
|||
* between pch encoders and cpu encoders. */
|
||||
bool has_pch_encoder;
|
||||
|
||||
/* CPU Transcoder for the pipe. Currently this can only differ from the
|
||||
* pipe on Haswell (where we have a special eDP transcoder). */
|
||||
enum transcoder cpu_transcoder;
|
||||
|
||||
/*
|
||||
* Use reduced/limited/broadcast rbg range, compressing from the full
|
||||
* range fed into the crtcs.
|
||||
|
@ -222,7 +230,6 @@ struct intel_crtc {
|
|||
struct drm_crtc base;
|
||||
enum pipe pipe;
|
||||
enum plane plane;
|
||||
enum transcoder cpu_transcoder;
|
||||
u8 lut_r[256], lut_g[256], lut_b[256];
|
||||
/*
|
||||
* Whether the crtc and the connected output pipeline is active. Implies
|
||||
|
@ -693,6 +700,7 @@ extern void intel_update_fbc(struct drm_device *dev);
|
|||
extern void intel_gpu_ips_init(struct drm_i915_private *dev_priv);
|
||||
extern void intel_gpu_ips_teardown(void);
|
||||
|
||||
extern bool intel_using_power_well(struct drm_device *dev);
|
||||
extern void intel_init_power_well(struct drm_device *dev);
|
||||
extern void intel_set_power_well(struct drm_device *dev, bool enable);
|
||||
extern void intel_enable_gt_powersave(struct drm_device *dev);
|
||||
|
|
|
@ -283,6 +283,9 @@ void intel_fb_restore_mode(struct drm_device *dev)
|
|||
struct drm_mode_config *config = &dev->mode_config;
|
||||
struct drm_plane *plane;
|
||||
|
||||
if (INTEL_INFO(dev)->num_pipes == 0)
|
||||
return;
|
||||
|
||||
drm_modeset_lock_all(dev);
|
||||
|
||||
ret = drm_fb_helper_restore_fbdev_mode(&dev_priv->fbdev->helper);
|
||||
|
|
|
@ -294,8 +294,8 @@ static void hsw_write_infoframe(struct drm_encoder *encoder,
|
|||
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);
|
||||
u32 ctl_reg = HSW_TVIDEO_DIP_CTL(intel_crtc->cpu_transcoder);
|
||||
u32 data_reg = hsw_infoframe_data_reg(frame, intel_crtc->cpu_transcoder);
|
||||
u32 ctl_reg = HSW_TVIDEO_DIP_CTL(intel_crtc->config.cpu_transcoder);
|
||||
u32 data_reg = hsw_infoframe_data_reg(frame, intel_crtc->config.cpu_transcoder);
|
||||
unsigned int i, len = DIP_HEADER_SIZE + frame->len;
|
||||
u32 val = I915_READ(ctl_reg);
|
||||
|
||||
|
@ -570,7 +570,7 @@ static void hsw_set_infoframes(struct drm_encoder *encoder,
|
|||
struct drm_i915_private *dev_priv = encoder->dev->dev_private;
|
||||
struct intel_crtc *intel_crtc = to_intel_crtc(encoder->crtc);
|
||||
struct intel_hdmi *intel_hdmi = enc_to_intel_hdmi(encoder);
|
||||
u32 reg = HSW_TVIDEO_DIP_CTL(intel_crtc->cpu_transcoder);
|
||||
u32 reg = HSW_TVIDEO_DIP_CTL(intel_crtc->config.cpu_transcoder);
|
||||
u32 val = I915_READ(reg);
|
||||
|
||||
assert_hdmi_port_disabled(intel_hdmi);
|
||||
|
@ -998,7 +998,6 @@ void intel_hdmi_init_connector(struct intel_digital_port *intel_dig_port,
|
|||
DRM_MODE_CONNECTOR_HDMIA);
|
||||
drm_connector_helper_add(connector, &intel_hdmi_connector_helper_funcs);
|
||||
|
||||
connector->polled = DRM_CONNECTOR_POLL_HPD;
|
||||
connector->interlace_allowed = 1;
|
||||
connector->doublescan_allowed = 0;
|
||||
|
||||
|
|
|
@ -522,7 +522,9 @@ int intel_setup_gmbus(struct drm_device *dev)
|
|||
struct drm_i915_private *dev_priv = dev->dev_private;
|
||||
int ret, i;
|
||||
|
||||
if (HAS_PCH_SPLIT(dev))
|
||||
if (HAS_PCH_NOP(dev))
|
||||
return 0;
|
||||
else if (HAS_PCH_SPLIT(dev))
|
||||
dev_priv->gpio_mmio_base = PCH_GPIOA - GPIOA;
|
||||
else if (IS_VALLEYVIEW(dev))
|
||||
dev_priv->gpio_mmio_base = VLV_DISPLAY_BASE;
|
||||
|
|
|
@ -631,7 +631,6 @@ static void intel_lvds_destroy(struct drm_connector *connector)
|
|||
if (!IS_ERR_OR_NULL(lvds_connector->base.edid))
|
||||
kfree(lvds_connector->base.edid);
|
||||
|
||||
intel_panel_destroy_backlight(connector->dev);
|
||||
intel_panel_fini(&lvds_connector->base.panel);
|
||||
|
||||
drm_sysfs_connector_remove(connector);
|
||||
|
|
|
@ -428,6 +428,9 @@ int intel_panel_setup_backlight(struct drm_connector *connector)
|
|||
|
||||
intel_panel_init_backlight(dev);
|
||||
|
||||
if (WARN_ON(dev_priv->backlight.device))
|
||||
return -ENODEV;
|
||||
|
||||
memset(&props, 0, sizeof(props));
|
||||
props.type = BACKLIGHT_RAW;
|
||||
props.brightness = dev_priv->backlight.level;
|
||||
|
@ -453,8 +456,10 @@ int intel_panel_setup_backlight(struct drm_connector *connector)
|
|||
void intel_panel_destroy_backlight(struct drm_device *dev)
|
||||
{
|
||||
struct drm_i915_private *dev_priv = dev->dev_private;
|
||||
if (dev_priv->backlight.device)
|
||||
if (dev_priv->backlight.device) {
|
||||
backlight_device_unregister(dev_priv->backlight.device);
|
||||
dev_priv->backlight.device = NULL;
|
||||
}
|
||||
}
|
||||
#else
|
||||
int intel_panel_setup_backlight(struct drm_connector *connector)
|
||||
|
|
|
@ -2558,8 +2558,8 @@ static void gen6_enable_rps(struct drm_device *dev)
|
|||
rp_state_cap = I915_READ(GEN6_RP_STATE_CAP);
|
||||
gt_perf_status = I915_READ(GEN6_GT_PERF_STATUS);
|
||||
|
||||
/* In units of 100MHz */
|
||||
dev_priv->rps.max_delay = rp_state_cap & 0xff;
|
||||
/* In units of 50MHz */
|
||||
dev_priv->rps.hw_max = dev_priv->rps.max_delay = rp_state_cap & 0xff;
|
||||
dev_priv->rps.min_delay = (rp_state_cap & 0xff0000) >> 16;
|
||||
dev_priv->rps.cur_delay = 0;
|
||||
|
||||
|
@ -2643,10 +2643,10 @@ static void gen6_enable_rps(struct drm_device *dev)
|
|||
pcu_mbox = 0;
|
||||
ret = sandybridge_pcode_read(dev_priv, GEN6_READ_OC_PARAMS, &pcu_mbox);
|
||||
if (!ret && (pcu_mbox & (1<<31))) { /* OC supported */
|
||||
DRM_DEBUG_DRIVER("overclocking supported, adjusting frequency max from %dMHz to %dMHz\n",
|
||||
DRM_DEBUG_DRIVER("Overclocking supported. Max: %dMHz, Overclock max: %dMHz\n",
|
||||
(dev_priv->rps.max_delay & 0xff) * 50,
|
||||
(pcu_mbox & 0xff) * 50);
|
||||
dev_priv->rps.max_delay = pcu_mbox & 0xff;
|
||||
dev_priv->rps.hw_max = pcu_mbox & 0xff;
|
||||
}
|
||||
} else {
|
||||
DRM_DEBUG_DRIVER("Failed to set the min frequency\n");
|
||||
|
@ -2684,8 +2684,8 @@ static void gen6_update_ring_freq(struct drm_device *dev)
|
|||
{
|
||||
struct drm_i915_private *dev_priv = dev->dev_private;
|
||||
int min_freq = 15;
|
||||
int gpu_freq;
|
||||
unsigned int ia_freq, max_ia_freq;
|
||||
unsigned int gpu_freq;
|
||||
unsigned int max_ia_freq, min_ring_freq;
|
||||
int scaling_factor = 180;
|
||||
|
||||
WARN_ON(!mutex_is_locked(&dev_priv->rps.hw_lock));
|
||||
|
@ -2701,6 +2701,10 @@ static void gen6_update_ring_freq(struct drm_device *dev)
|
|||
/* Convert from kHz to MHz */
|
||||
max_ia_freq /= 1000;
|
||||
|
||||
min_ring_freq = I915_READ(MCHBAR_MIRROR_BASE_SNB + DCLK);
|
||||
/* convert DDR frequency from units of 133.3MHz to bandwidth */
|
||||
min_ring_freq = (2 * 4 * min_ring_freq + 2) / 3;
|
||||
|
||||
/*
|
||||
* For each potential GPU frequency, load a ring frequency we'd like
|
||||
* to use for memory access. We do this by specifying the IA frequency
|
||||
|
@ -2709,21 +2713,32 @@ static void gen6_update_ring_freq(struct drm_device *dev)
|
|||
for (gpu_freq = dev_priv->rps.max_delay; gpu_freq >= dev_priv->rps.min_delay;
|
||||
gpu_freq--) {
|
||||
int diff = dev_priv->rps.max_delay - gpu_freq;
|
||||
unsigned int ia_freq = 0, ring_freq = 0;
|
||||
|
||||
/*
|
||||
* For GPU frequencies less than 750MHz, just use the lowest
|
||||
* ring freq.
|
||||
*/
|
||||
if (gpu_freq < min_freq)
|
||||
ia_freq = 800;
|
||||
else
|
||||
ia_freq = max_ia_freq - ((diff * scaling_factor) / 2);
|
||||
ia_freq = DIV_ROUND_CLOSEST(ia_freq, 100);
|
||||
ia_freq <<= GEN6_PCODE_FREQ_IA_RATIO_SHIFT;
|
||||
if (IS_HASWELL(dev)) {
|
||||
ring_freq = (gpu_freq * 5 + 3) / 4;
|
||||
ring_freq = max(min_ring_freq, ring_freq);
|
||||
/* leave ia_freq as the default, chosen by cpufreq */
|
||||
} else {
|
||||
/* On older processors, there is no separate ring
|
||||
* clock domain, so in order to boost the bandwidth
|
||||
* of the ring, we need to upclock the CPU (ia_freq).
|
||||
*
|
||||
* For GPU frequencies less than 750MHz,
|
||||
* just use the lowest ring freq.
|
||||
*/
|
||||
if (gpu_freq < min_freq)
|
||||
ia_freq = 800;
|
||||
else
|
||||
ia_freq = max_ia_freq - ((diff * scaling_factor) / 2);
|
||||
ia_freq = DIV_ROUND_CLOSEST(ia_freq, 100);
|
||||
}
|
||||
|
||||
sandybridge_pcode_write(dev_priv,
|
||||
GEN6_PCODE_WRITE_MIN_FREQ_TABLE,
|
||||
ia_freq | gpu_freq);
|
||||
ia_freq << GEN6_PCODE_FREQ_IA_RATIO_SHIFT |
|
||||
ring_freq << GEN6_PCODE_FREQ_RING_RATIO_SHIFT |
|
||||
gpu_freq);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -3575,6 +3590,7 @@ static void cpt_init_clock_gating(struct drm_device *dev)
|
|||
{
|
||||
struct drm_i915_private *dev_priv = dev->dev_private;
|
||||
int pipe;
|
||||
uint32_t val;
|
||||
|
||||
/*
|
||||
* On Ibex Peak and Cougar Point, we need to disable clock
|
||||
|
@ -3587,8 +3603,17 @@ static void cpt_init_clock_gating(struct drm_device *dev)
|
|||
/* The below fixes the weird display corruption, a few pixels shifted
|
||||
* downward, on (only) LVDS of some HP laptops with IVY.
|
||||
*/
|
||||
for_each_pipe(pipe)
|
||||
I915_WRITE(TRANS_CHICKEN2(pipe), TRANS_CHICKEN2_TIMING_OVERRIDE);
|
||||
for_each_pipe(pipe) {
|
||||
val = I915_READ(TRANS_CHICKEN2(pipe));
|
||||
val |= TRANS_CHICKEN2_TIMING_OVERRIDE;
|
||||
val &= ~TRANS_CHICKEN2_FDI_POLARITY_REVERSED;
|
||||
if (dev_priv->fdi_rx_polarity_inverted)
|
||||
val |= TRANS_CHICKEN2_FDI_POLARITY_REVERSED;
|
||||
val &= ~TRANS_CHICKEN2_FRAME_START_DELAY_MASK;
|
||||
val &= ~TRANS_CHICKEN2_DISABLE_DEEP_COLOR_COUNTER;
|
||||
val &= ~TRANS_CHICKEN2_DISABLE_DEEP_COLOR_MODESWITCH;
|
||||
I915_WRITE(TRANS_CHICKEN2(pipe), val);
|
||||
}
|
||||
/* WADP0ClockGatingDisable */
|
||||
for_each_pipe(pipe) {
|
||||
I915_WRITE(TRANS_CHICKEN1(pipe),
|
||||
|
@ -3890,7 +3915,8 @@ static void ivybridge_init_clock_gating(struct drm_device *dev)
|
|||
snpcr |= GEN6_MBC_SNPCR_MED;
|
||||
I915_WRITE(GEN6_MBCUNIT_SNPCR, snpcr);
|
||||
|
||||
cpt_init_clock_gating(dev);
|
||||
if (!HAS_PCH_NOP(dev))
|
||||
cpt_init_clock_gating(dev);
|
||||
|
||||
gen6_check_mch_setup(dev);
|
||||
}
|
||||
|
@ -4084,6 +4110,22 @@ void intel_init_clock_gating(struct drm_device *dev)
|
|||
dev_priv->display.init_clock_gating(dev);
|
||||
}
|
||||
|
||||
/**
|
||||
* We should only use the power well if we explicitly asked the hardware to
|
||||
* enable it, so check if it's enabled and also check if we've requested it to
|
||||
* be enabled.
|
||||
*/
|
||||
bool intel_using_power_well(struct drm_device *dev)
|
||||
{
|
||||
struct drm_i915_private *dev_priv = dev->dev_private;
|
||||
|
||||
if (IS_HASWELL(dev))
|
||||
return I915_READ(HSW_PWR_WELL_DRIVER) ==
|
||||
(HSW_PWR_WELL_ENABLE | HSW_PWR_WELL_STATE);
|
||||
else
|
||||
return true;
|
||||
}
|
||||
|
||||
void intel_set_power_well(struct drm_device *dev, bool enable)
|
||||
{
|
||||
struct drm_i915_private *dev_priv = dev->dev_private;
|
||||
|
@ -4190,7 +4232,6 @@ void intel_init_pm(struct drm_device *dev)
|
|||
}
|
||||
dev_priv->display.init_clock_gating = gen6_init_clock_gating;
|
||||
} else if (IS_IVYBRIDGE(dev)) {
|
||||
/* FIXME: detect B0+ stepping and use auto training */
|
||||
if (SNB_READ_WM0_LATENCY()) {
|
||||
dev_priv->display.update_wm = ivybridge_update_wm;
|
||||
dev_priv->display.update_sprite_wm = sandybridge_update_sprite_wm;
|
||||
|
|
|
@ -1231,12 +1231,8 @@ static bool intel_sdvo_connector_get_hw_state(struct intel_connector *connector)
|
|||
struct intel_sdvo_connector *intel_sdvo_connector =
|
||||
to_intel_sdvo_connector(&connector->base);
|
||||
struct intel_sdvo *intel_sdvo = intel_attached_sdvo(&connector->base);
|
||||
struct drm_i915_private *dev_priv = intel_sdvo->base.base.dev->dev_private;
|
||||
u16 active_outputs;
|
||||
|
||||
if (!(I915_READ(intel_sdvo->sdvo_reg) & SDVO_ENABLE))
|
||||
return false;
|
||||
|
||||
intel_sdvo_get_active_outputs(intel_sdvo, &active_outputs);
|
||||
|
||||
if (active_outputs & intel_sdvo_connector->output_flag)
|
||||
|
@ -1251,11 +1247,13 @@ static bool intel_sdvo_get_hw_state(struct intel_encoder *encoder,
|
|||
struct drm_device *dev = encoder->base.dev;
|
||||
struct drm_i915_private *dev_priv = dev->dev_private;
|
||||
struct intel_sdvo *intel_sdvo = to_intel_sdvo(&encoder->base);
|
||||
u16 active_outputs;
|
||||
u32 tmp;
|
||||
|
||||
tmp = I915_READ(intel_sdvo->sdvo_reg);
|
||||
intel_sdvo_get_active_outputs(intel_sdvo, &active_outputs);
|
||||
|
||||
if (!(tmp & SDVO_ENABLE))
|
||||
if (!(tmp & SDVO_ENABLE) && (active_outputs == 0))
|
||||
return false;
|
||||
|
||||
if (HAS_PCH_CPT(dev))
|
||||
|
@ -2276,7 +2274,6 @@ intel_sdvo_dvi_init(struct intel_sdvo *intel_sdvo, int device)
|
|||
connector = &intel_connector->base;
|
||||
if (intel_sdvo_get_hotplug_support(intel_sdvo) &
|
||||
intel_sdvo_connector->output_flag) {
|
||||
connector->polled = DRM_CONNECTOR_POLL_HPD;
|
||||
intel_sdvo->hotplug_active |= intel_sdvo_connector->output_flag;
|
||||
/* Some SDVO devices have one-shot hotplug interrupts.
|
||||
* Ensure that they get re-enabled when an interrupt happens.
|
||||
|
@ -2284,7 +2281,7 @@ intel_sdvo_dvi_init(struct intel_sdvo *intel_sdvo, int device)
|
|||
intel_encoder->hot_plug = intel_sdvo_enable_hotplug;
|
||||
intel_sdvo_enable_hotplug(intel_encoder);
|
||||
} else {
|
||||
connector->polled = DRM_CONNECTOR_POLL_CONNECT | DRM_CONNECTOR_POLL_DISCONNECT;
|
||||
intel_connector->polled = DRM_CONNECTOR_POLL_CONNECT | DRM_CONNECTOR_POLL_DISCONNECT;
|
||||
}
|
||||
encoder->encoder_type = DRM_MODE_ENCODER_TMDS;
|
||||
connector->connector_type = DRM_MODE_CONNECTOR_DVID;
|
||||
|
@ -2353,7 +2350,7 @@ intel_sdvo_analog_init(struct intel_sdvo *intel_sdvo, int device)
|
|||
|
||||
intel_connector = &intel_sdvo_connector->base;
|
||||
connector = &intel_connector->base;
|
||||
connector->polled = DRM_CONNECTOR_POLL_CONNECT;
|
||||
intel_connector->polled = DRM_CONNECTOR_POLL_CONNECT;
|
||||
encoder->encoder_type = DRM_MODE_ENCODER_DAC;
|
||||
connector->connector_type = DRM_MODE_CONNECTOR_VGA;
|
||||
|
||||
|
@ -2746,7 +2743,6 @@ bool intel_sdvo_init(struct drm_device *dev, uint32_t sdvo_reg, bool is_sdvob)
|
|||
struct intel_sdvo *intel_sdvo;
|
||||
u32 hotplug_mask;
|
||||
int i;
|
||||
|
||||
intel_sdvo = kzalloc(sizeof(struct intel_sdvo), GFP_KERNEL);
|
||||
if (!intel_sdvo)
|
||||
return false;
|
||||
|
|
|
@ -1613,7 +1613,7 @@ intel_tv_init(struct drm_device *dev)
|
|||
*
|
||||
* More recent chipsets favour HDMI rather than integrated S-Video.
|
||||
*/
|
||||
connector->polled = DRM_CONNECTOR_POLL_CONNECT;
|
||||
intel_connector->polled = DRM_CONNECTOR_POLL_CONNECT;
|
||||
|
||||
drm_connector_init(dev, connector, &intel_tv_connector_funcs,
|
||||
DRM_MODE_CONNECTOR_SVIDEO);
|
||||
|
|
Loading…
Reference in New Issue