Merge tag 'drm-intel-next-2013-12-13' of git://people.freedesktop.org/~danvet/drm-intel into drm-next
- fbc1 improvements from Ville (pre-gm45). - vlv forcewake improvements from Deepak S. - Some corner-cases fixes from Mika for the context hang stat code. - pc8 improvements and prep work for runtime D3 from Paulo, almost ready for primetime. - gen2 dpll fixes from Ville. - DSI improvements from Shobhit Kumar. - A few smaller fixes and improvements all over. [airlied: intel_ddi.c conflict fixed up] * tag 'drm-intel-next-2013-12-13' of git://people.freedesktop.org/~danvet/drm-intel: (61 commits) drm/i915/bdw: Implement ff workarounds drm/i915/bdw: Force all Data Cache Data Port access to be Non-Coherent drm/i915/bdw: Don't use forcewake needlessly drm/i915: Clear out old GT FIFO errors in intel_uncore_early_sanitize() drm/i915: dont call irq_put when irq test is on drm/i915: Rework the FBC interval/stall stuff a bit drm/i915: Enable FBC for all mobile gen2 and gen3 platforms drm/i915: FBC_CONTROL2 is gen4 only drm/i915: Gen2 FBC1 CFB pitch wants 32B units drm/i915: split intel_ddi_pll_mode_set in 2 pieces drm/i915: Fix timeout with missed interrupts in __wait_seqno drm/i915: touch VGA MSR after we enable the power well drm/i915: extract hsw_power_well_post_{enable, disable} drm/i915: remove i915_disable_vga_mem declaration drm/i915: Parametrize the dphy and other spec specific parameters drm/i915: Remove redundant DSI PLL enabling drm/i915: Reorganize the DSI enable/disable sequence drm/i915: Try harder to get best m, n, p values with minimal error drm/i915: Compute dsi_clk from pixel clock drm/i915: Use FLISDSI interface for band gap reset ... Conflicts: drivers/gpu/drm/i915/intel_ddi.c
This commit is contained in:
@@ -564,10 +564,12 @@ static int i915_gem_seqno_info(struct seq_file *m, void *data)
|
|||||||
ret = mutex_lock_interruptible(&dev->struct_mutex);
|
ret = mutex_lock_interruptible(&dev->struct_mutex);
|
||||||
if (ret)
|
if (ret)
|
||||||
return ret;
|
return ret;
|
||||||
|
intel_runtime_pm_get(dev_priv);
|
||||||
|
|
||||||
for_each_ring(ring, dev_priv, i)
|
for_each_ring(ring, dev_priv, i)
|
||||||
i915_ring_seqno_info(m, ring);
|
i915_ring_seqno_info(m, ring);
|
||||||
|
|
||||||
|
intel_runtime_pm_put(dev_priv);
|
||||||
mutex_unlock(&dev->struct_mutex);
|
mutex_unlock(&dev->struct_mutex);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
@@ -585,6 +587,7 @@ static int i915_interrupt_info(struct seq_file *m, void *data)
|
|||||||
ret = mutex_lock_interruptible(&dev->struct_mutex);
|
ret = mutex_lock_interruptible(&dev->struct_mutex);
|
||||||
if (ret)
|
if (ret)
|
||||||
return ret;
|
return ret;
|
||||||
|
intel_runtime_pm_get(dev_priv);
|
||||||
|
|
||||||
if (INTEL_INFO(dev)->gen >= 8) {
|
if (INTEL_INFO(dev)->gen >= 8) {
|
||||||
int i;
|
int i;
|
||||||
@@ -711,6 +714,7 @@ static int i915_interrupt_info(struct seq_file *m, void *data)
|
|||||||
}
|
}
|
||||||
i915_ring_seqno_info(m, ring);
|
i915_ring_seqno_info(m, ring);
|
||||||
}
|
}
|
||||||
|
intel_runtime_pm_put(dev_priv);
|
||||||
mutex_unlock(&dev->struct_mutex);
|
mutex_unlock(&dev->struct_mutex);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
@@ -904,9 +908,11 @@ static int i915_rstdby_delays(struct seq_file *m, void *unused)
|
|||||||
ret = mutex_lock_interruptible(&dev->struct_mutex);
|
ret = mutex_lock_interruptible(&dev->struct_mutex);
|
||||||
if (ret)
|
if (ret)
|
||||||
return ret;
|
return ret;
|
||||||
|
intel_runtime_pm_get(dev_priv);
|
||||||
|
|
||||||
crstanddelay = I915_READ16(CRSTANDVID);
|
crstanddelay = I915_READ16(CRSTANDVID);
|
||||||
|
|
||||||
|
intel_runtime_pm_put(dev_priv);
|
||||||
mutex_unlock(&dev->struct_mutex);
|
mutex_unlock(&dev->struct_mutex);
|
||||||
|
|
||||||
seq_printf(m, "w/ctx: %d, w/o ctx: %d\n", (crstanddelay >> 8) & 0x3f, (crstanddelay & 0x3f));
|
seq_printf(m, "w/ctx: %d, w/o ctx: %d\n", (crstanddelay >> 8) & 0x3f, (crstanddelay & 0x3f));
|
||||||
@@ -919,7 +925,9 @@ static int i915_cur_delayinfo(struct seq_file *m, void *unused)
|
|||||||
struct drm_info_node *node = (struct drm_info_node *) m->private;
|
struct drm_info_node *node = (struct drm_info_node *) m->private;
|
||||||
struct drm_device *dev = node->minor->dev;
|
struct drm_device *dev = node->minor->dev;
|
||||||
drm_i915_private_t *dev_priv = dev->dev_private;
|
drm_i915_private_t *dev_priv = dev->dev_private;
|
||||||
int ret;
|
int ret = 0;
|
||||||
|
|
||||||
|
intel_runtime_pm_get(dev_priv);
|
||||||
|
|
||||||
flush_delayed_work(&dev_priv->rps.delayed_resume_work);
|
flush_delayed_work(&dev_priv->rps.delayed_resume_work);
|
||||||
|
|
||||||
@@ -945,7 +953,7 @@ static int i915_cur_delayinfo(struct seq_file *m, void *unused)
|
|||||||
/* RPSTAT1 is in the GT power well */
|
/* RPSTAT1 is in the GT power well */
|
||||||
ret = mutex_lock_interruptible(&dev->struct_mutex);
|
ret = mutex_lock_interruptible(&dev->struct_mutex);
|
||||||
if (ret)
|
if (ret)
|
||||||
return ret;
|
goto out;
|
||||||
|
|
||||||
gen6_gt_force_wake_get(dev_priv, FORCEWAKE_ALL);
|
gen6_gt_force_wake_get(dev_priv, FORCEWAKE_ALL);
|
||||||
|
|
||||||
@@ -1033,7 +1041,9 @@ static int i915_cur_delayinfo(struct seq_file *m, void *unused)
|
|||||||
seq_puts(m, "no P-state info available\n");
|
seq_puts(m, "no P-state info available\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0;
|
out:
|
||||||
|
intel_runtime_pm_put(dev_priv);
|
||||||
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int i915_delayfreq_table(struct seq_file *m, void *unused)
|
static int i915_delayfreq_table(struct seq_file *m, void *unused)
|
||||||
@@ -1047,6 +1057,7 @@ static int i915_delayfreq_table(struct seq_file *m, void *unused)
|
|||||||
ret = mutex_lock_interruptible(&dev->struct_mutex);
|
ret = mutex_lock_interruptible(&dev->struct_mutex);
|
||||||
if (ret)
|
if (ret)
|
||||||
return ret;
|
return ret;
|
||||||
|
intel_runtime_pm_get(dev_priv);
|
||||||
|
|
||||||
for (i = 0; i < 16; i++) {
|
for (i = 0; i < 16; i++) {
|
||||||
delayfreq = I915_READ(PXVFREQ_BASE + i * 4);
|
delayfreq = I915_READ(PXVFREQ_BASE + i * 4);
|
||||||
@@ -1054,6 +1065,8 @@ static int i915_delayfreq_table(struct seq_file *m, void *unused)
|
|||||||
(delayfreq & PXVFREQ_PX_MASK) >> PXVFREQ_PX_SHIFT);
|
(delayfreq & PXVFREQ_PX_MASK) >> PXVFREQ_PX_SHIFT);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
intel_runtime_pm_put(dev_priv);
|
||||||
|
|
||||||
mutex_unlock(&dev->struct_mutex);
|
mutex_unlock(&dev->struct_mutex);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
@@ -1075,12 +1088,14 @@ static int i915_inttoext_table(struct seq_file *m, void *unused)
|
|||||||
ret = mutex_lock_interruptible(&dev->struct_mutex);
|
ret = mutex_lock_interruptible(&dev->struct_mutex);
|
||||||
if (ret)
|
if (ret)
|
||||||
return ret;
|
return ret;
|
||||||
|
intel_runtime_pm_get(dev_priv);
|
||||||
|
|
||||||
for (i = 1; i <= 32; i++) {
|
for (i = 1; i <= 32; i++) {
|
||||||
inttoext = I915_READ(INTTOEXT_BASE_ILK + i * 4);
|
inttoext = I915_READ(INTTOEXT_BASE_ILK + i * 4);
|
||||||
seq_printf(m, "INTTOEXT%02d: 0x%08x\n", i, inttoext);
|
seq_printf(m, "INTTOEXT%02d: 0x%08x\n", i, inttoext);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
intel_runtime_pm_put(dev_priv);
|
||||||
mutex_unlock(&dev->struct_mutex);
|
mutex_unlock(&dev->struct_mutex);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
@@ -1098,11 +1113,13 @@ static int ironlake_drpc_info(struct seq_file *m)
|
|||||||
ret = mutex_lock_interruptible(&dev->struct_mutex);
|
ret = mutex_lock_interruptible(&dev->struct_mutex);
|
||||||
if (ret)
|
if (ret)
|
||||||
return ret;
|
return ret;
|
||||||
|
intel_runtime_pm_get(dev_priv);
|
||||||
|
|
||||||
rgvmodectl = I915_READ(MEMMODECTL);
|
rgvmodectl = I915_READ(MEMMODECTL);
|
||||||
rstdbyctl = I915_READ(RSTDBYCTL);
|
rstdbyctl = I915_READ(RSTDBYCTL);
|
||||||
crstandvid = I915_READ16(CRSTANDVID);
|
crstandvid = I915_READ16(CRSTANDVID);
|
||||||
|
|
||||||
|
intel_runtime_pm_put(dev_priv);
|
||||||
mutex_unlock(&dev->struct_mutex);
|
mutex_unlock(&dev->struct_mutex);
|
||||||
|
|
||||||
seq_printf(m, "HD boost: %s\n", (rgvmodectl & MEMMODE_BOOST_EN) ?
|
seq_printf(m, "HD boost: %s\n", (rgvmodectl & MEMMODE_BOOST_EN) ?
|
||||||
@@ -1166,6 +1183,7 @@ static int gen6_drpc_info(struct seq_file *m)
|
|||||||
ret = mutex_lock_interruptible(&dev->struct_mutex);
|
ret = mutex_lock_interruptible(&dev->struct_mutex);
|
||||||
if (ret)
|
if (ret)
|
||||||
return ret;
|
return ret;
|
||||||
|
intel_runtime_pm_get(dev_priv);
|
||||||
|
|
||||||
spin_lock_irq(&dev_priv->uncore.lock);
|
spin_lock_irq(&dev_priv->uncore.lock);
|
||||||
forcewake_count = dev_priv->uncore.forcewake_count;
|
forcewake_count = dev_priv->uncore.forcewake_count;
|
||||||
@@ -1191,6 +1209,8 @@ static int gen6_drpc_info(struct seq_file *m)
|
|||||||
sandybridge_pcode_read(dev_priv, GEN6_PCODE_READ_RC6VIDS, &rc6vids);
|
sandybridge_pcode_read(dev_priv, GEN6_PCODE_READ_RC6VIDS, &rc6vids);
|
||||||
mutex_unlock(&dev_priv->rps.hw_lock);
|
mutex_unlock(&dev_priv->rps.hw_lock);
|
||||||
|
|
||||||
|
intel_runtime_pm_put(dev_priv);
|
||||||
|
|
||||||
seq_printf(m, "Video Turbo Mode: %s\n",
|
seq_printf(m, "Video Turbo Mode: %s\n",
|
||||||
yesno(rpmodectl1 & GEN6_RP_MEDIA_TURBO));
|
yesno(rpmodectl1 & GEN6_RP_MEDIA_TURBO));
|
||||||
seq_printf(m, "HW control enabled: %s\n",
|
seq_printf(m, "HW control enabled: %s\n",
|
||||||
@@ -1405,6 +1425,7 @@ static int i915_ring_freq_table(struct seq_file *m, void *unused)
|
|||||||
ret = mutex_lock_interruptible(&dev_priv->rps.hw_lock);
|
ret = mutex_lock_interruptible(&dev_priv->rps.hw_lock);
|
||||||
if (ret)
|
if (ret)
|
||||||
return ret;
|
return ret;
|
||||||
|
intel_runtime_pm_get(dev_priv);
|
||||||
|
|
||||||
seq_puts(m, "GPU freq (MHz)\tEffective CPU freq (MHz)\tEffective Ring freq (MHz)\n");
|
seq_puts(m, "GPU freq (MHz)\tEffective CPU freq (MHz)\tEffective Ring freq (MHz)\n");
|
||||||
|
|
||||||
@@ -1421,6 +1442,7 @@ static int i915_ring_freq_table(struct seq_file *m, void *unused)
|
|||||||
((ia_freq >> 8) & 0xff) * 100);
|
((ia_freq >> 8) & 0xff) * 100);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
intel_runtime_pm_put(dev_priv);
|
||||||
mutex_unlock(&dev_priv->rps.hw_lock);
|
mutex_unlock(&dev_priv->rps.hw_lock);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
@@ -1436,8 +1458,10 @@ static int i915_gfxec(struct seq_file *m, void *unused)
|
|||||||
ret = mutex_lock_interruptible(&dev->struct_mutex);
|
ret = mutex_lock_interruptible(&dev->struct_mutex);
|
||||||
if (ret)
|
if (ret)
|
||||||
return ret;
|
return ret;
|
||||||
|
intel_runtime_pm_get(dev_priv);
|
||||||
|
|
||||||
seq_printf(m, "GFXEC: %ld\n", (unsigned long)I915_READ(0x112f4));
|
seq_printf(m, "GFXEC: %ld\n", (unsigned long)I915_READ(0x112f4));
|
||||||
|
intel_runtime_pm_put(dev_priv);
|
||||||
|
|
||||||
mutex_unlock(&dev->struct_mutex);
|
mutex_unlock(&dev->struct_mutex);
|
||||||
|
|
||||||
@@ -1617,6 +1641,7 @@ static int i915_swizzle_info(struct seq_file *m, void *data)
|
|||||||
ret = mutex_lock_interruptible(&dev->struct_mutex);
|
ret = mutex_lock_interruptible(&dev->struct_mutex);
|
||||||
if (ret)
|
if (ret)
|
||||||
return ret;
|
return ret;
|
||||||
|
intel_runtime_pm_get(dev_priv);
|
||||||
|
|
||||||
seq_printf(m, "bit6 swizzle for X-tiling = %s\n",
|
seq_printf(m, "bit6 swizzle for X-tiling = %s\n",
|
||||||
swizzle_string(dev_priv->mm.bit_6_swizzle_x));
|
swizzle_string(dev_priv->mm.bit_6_swizzle_x));
|
||||||
@@ -1648,6 +1673,7 @@ static int i915_swizzle_info(struct seq_file *m, void *data)
|
|||||||
seq_printf(m, "DISP_ARB_CTL = 0x%08x\n",
|
seq_printf(m, "DISP_ARB_CTL = 0x%08x\n",
|
||||||
I915_READ(DISP_ARB_CTL));
|
I915_READ(DISP_ARB_CTL));
|
||||||
}
|
}
|
||||||
|
intel_runtime_pm_put(dev_priv);
|
||||||
mutex_unlock(&dev->struct_mutex);
|
mutex_unlock(&dev->struct_mutex);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
@@ -1708,16 +1734,19 @@ static int i915_ppgtt_info(struct seq_file *m, void *data)
|
|||||||
{
|
{
|
||||||
struct drm_info_node *node = (struct drm_info_node *) m->private;
|
struct drm_info_node *node = (struct drm_info_node *) m->private;
|
||||||
struct drm_device *dev = node->minor->dev;
|
struct drm_device *dev = node->minor->dev;
|
||||||
|
struct drm_i915_private *dev_priv = dev->dev_private;
|
||||||
|
|
||||||
int ret = mutex_lock_interruptible(&dev->struct_mutex);
|
int ret = mutex_lock_interruptible(&dev->struct_mutex);
|
||||||
if (ret)
|
if (ret)
|
||||||
return ret;
|
return ret;
|
||||||
|
intel_runtime_pm_get(dev_priv);
|
||||||
|
|
||||||
if (INTEL_INFO(dev)->gen >= 8)
|
if (INTEL_INFO(dev)->gen >= 8)
|
||||||
gen8_ppgtt_info(m, dev);
|
gen8_ppgtt_info(m, dev);
|
||||||
else if (INTEL_INFO(dev)->gen >= 6)
|
else if (INTEL_INFO(dev)->gen >= 6)
|
||||||
gen6_ppgtt_info(m, dev);
|
gen6_ppgtt_info(m, dev);
|
||||||
|
|
||||||
|
intel_runtime_pm_put(dev_priv);
|
||||||
mutex_unlock(&dev->struct_mutex);
|
mutex_unlock(&dev->struct_mutex);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
@@ -1791,6 +1820,8 @@ static int i915_edp_psr_status(struct seq_file *m, void *data)
|
|||||||
u32 psrperf = 0;
|
u32 psrperf = 0;
|
||||||
bool enabled = false;
|
bool enabled = false;
|
||||||
|
|
||||||
|
intel_runtime_pm_get(dev_priv);
|
||||||
|
|
||||||
seq_printf(m, "Sink_Support: %s\n", yesno(dev_priv->psr.sink_support));
|
seq_printf(m, "Sink_Support: %s\n", yesno(dev_priv->psr.sink_support));
|
||||||
seq_printf(m, "Source_OK: %s\n", yesno(dev_priv->psr.source_ok));
|
seq_printf(m, "Source_OK: %s\n", yesno(dev_priv->psr.source_ok));
|
||||||
|
|
||||||
@@ -1803,6 +1834,7 @@ static int i915_edp_psr_status(struct seq_file *m, void *data)
|
|||||||
EDP_PSR_PERF_CNT_MASK;
|
EDP_PSR_PERF_CNT_MASK;
|
||||||
seq_printf(m, "Performance_Counter: %u\n", psrperf);
|
seq_printf(m, "Performance_Counter: %u\n", psrperf);
|
||||||
|
|
||||||
|
intel_runtime_pm_put(dev_priv);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -3016,8 +3048,11 @@ i915_cache_sharing_get(void *data, u64 *val)
|
|||||||
ret = mutex_lock_interruptible(&dev->struct_mutex);
|
ret = mutex_lock_interruptible(&dev->struct_mutex);
|
||||||
if (ret)
|
if (ret)
|
||||||
return ret;
|
return ret;
|
||||||
|
intel_runtime_pm_get(dev_priv);
|
||||||
|
|
||||||
snpcr = I915_READ(GEN6_MBCUNIT_SNPCR);
|
snpcr = I915_READ(GEN6_MBCUNIT_SNPCR);
|
||||||
|
|
||||||
|
intel_runtime_pm_put(dev_priv);
|
||||||
mutex_unlock(&dev_priv->dev->struct_mutex);
|
mutex_unlock(&dev_priv->dev->struct_mutex);
|
||||||
|
|
||||||
*val = (snpcr & GEN6_MBC_SNPCR_MASK) >> GEN6_MBC_SNPCR_SHIFT;
|
*val = (snpcr & GEN6_MBC_SNPCR_MASK) >> GEN6_MBC_SNPCR_SHIFT;
|
||||||
@@ -3038,6 +3073,7 @@ i915_cache_sharing_set(void *data, u64 val)
|
|||||||
if (val > 3)
|
if (val > 3)
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
|
|
||||||
|
intel_runtime_pm_get(dev_priv);
|
||||||
DRM_DEBUG_DRIVER("Manually setting uncore sharing to %llu\n", val);
|
DRM_DEBUG_DRIVER("Manually setting uncore sharing to %llu\n", val);
|
||||||
|
|
||||||
/* Update the cache sharing policy here as well */
|
/* Update the cache sharing policy here as well */
|
||||||
@@ -3046,6 +3082,7 @@ i915_cache_sharing_set(void *data, u64 val)
|
|||||||
snpcr |= (val << GEN6_MBC_SNPCR_SHIFT);
|
snpcr |= (val << GEN6_MBC_SNPCR_SHIFT);
|
||||||
I915_WRITE(GEN6_MBCUNIT_SNPCR, snpcr);
|
I915_WRITE(GEN6_MBCUNIT_SNPCR, snpcr);
|
||||||
|
|
||||||
|
intel_runtime_pm_put(dev_priv);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -3061,6 +3098,7 @@ static int i915_forcewake_open(struct inode *inode, struct file *file)
|
|||||||
if (INTEL_INFO(dev)->gen < 6)
|
if (INTEL_INFO(dev)->gen < 6)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
|
intel_runtime_pm_get(dev_priv);
|
||||||
gen6_gt_force_wake_get(dev_priv, FORCEWAKE_ALL);
|
gen6_gt_force_wake_get(dev_priv, FORCEWAKE_ALL);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
@@ -3075,6 +3113,7 @@ static int i915_forcewake_release(struct inode *inode, struct file *file)
|
|||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
gen6_gt_force_wake_put(dev_priv, FORCEWAKE_ALL);
|
gen6_gt_force_wake_put(dev_priv, FORCEWAKE_ALL);
|
||||||
|
intel_runtime_pm_put(dev_priv);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
@@ -42,6 +42,8 @@
|
|||||||
#include <linux/vga_switcheroo.h>
|
#include <linux/vga_switcheroo.h>
|
||||||
#include <linux/slab.h>
|
#include <linux/slab.h>
|
||||||
#include <acpi/video.h>
|
#include <acpi/video.h>
|
||||||
|
#include <linux/pm.h>
|
||||||
|
#include <linux/pm_runtime.h>
|
||||||
|
|
||||||
#define LP_RING(d) (&((struct drm_i915_private *)(d))->ring[RCS])
|
#define LP_RING(d) (&((struct drm_i915_private *)(d))->ring[RCS])
|
||||||
|
|
||||||
@@ -1667,6 +1669,8 @@ int i915_driver_load(struct drm_device *dev, unsigned long flags)
|
|||||||
if (IS_GEN5(dev))
|
if (IS_GEN5(dev))
|
||||||
intel_gpu_ips_init(dev_priv);
|
intel_gpu_ips_init(dev_priv);
|
||||||
|
|
||||||
|
intel_init_runtime_pm(dev_priv);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
out_power_well:
|
out_power_well:
|
||||||
@@ -1706,6 +1710,14 @@ int i915_driver_unload(struct drm_device *dev)
|
|||||||
struct drm_i915_private *dev_priv = dev->dev_private;
|
struct drm_i915_private *dev_priv = dev->dev_private;
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
|
ret = i915_gem_suspend(dev);
|
||||||
|
if (ret) {
|
||||||
|
DRM_ERROR("failed to idle hardware: %d\n", ret);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
intel_fini_runtime_pm(dev_priv);
|
||||||
|
|
||||||
intel_gpu_ips_teardown();
|
intel_gpu_ips_teardown();
|
||||||
|
|
||||||
/* The i915.ko module is still not prepared to be loaded when
|
/* The i915.ko module is still not prepared to be loaded when
|
||||||
@@ -1719,10 +1731,6 @@ int i915_driver_unload(struct drm_device *dev)
|
|||||||
if (dev_priv->mm.inactive_shrinker.scan_objects)
|
if (dev_priv->mm.inactive_shrinker.scan_objects)
|
||||||
unregister_shrinker(&dev_priv->mm.inactive_shrinker);
|
unregister_shrinker(&dev_priv->mm.inactive_shrinker);
|
||||||
|
|
||||||
ret = i915_gem_suspend(dev);
|
|
||||||
if (ret)
|
|
||||||
DRM_ERROR("failed to idle hardware: %d\n", ret);
|
|
||||||
|
|
||||||
io_mapping_free(dev_priv->gtt.mappable);
|
io_mapping_free(dev_priv->gtt.mappable);
|
||||||
arch_phys_wc_del(dev_priv->gtt.mtrr);
|
arch_phys_wc_del(dev_priv->gtt.mtrr);
|
||||||
|
|
||||||
|
@@ -172,6 +172,7 @@ static const struct intel_device_info intel_i85x_info = {
|
|||||||
.gen = 2, .is_i85x = 1, .is_mobile = 1, .num_pipes = 2,
|
.gen = 2, .is_i85x = 1, .is_mobile = 1, .num_pipes = 2,
|
||||||
.cursor_needs_physical = 1,
|
.cursor_needs_physical = 1,
|
||||||
.has_overlay = 1, .overlay_needs_physical = 1,
|
.has_overlay = 1, .overlay_needs_physical = 1,
|
||||||
|
.has_fbc = 1,
|
||||||
.ring_mask = RENDER_RING,
|
.ring_mask = RENDER_RING,
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -191,6 +192,7 @@ static const struct intel_device_info intel_i915gm_info = {
|
|||||||
.cursor_needs_physical = 1,
|
.cursor_needs_physical = 1,
|
||||||
.has_overlay = 1, .overlay_needs_physical = 1,
|
.has_overlay = 1, .overlay_needs_physical = 1,
|
||||||
.supports_tv = 1,
|
.supports_tv = 1,
|
||||||
|
.has_fbc = 1,
|
||||||
.ring_mask = RENDER_RING,
|
.ring_mask = RENDER_RING,
|
||||||
};
|
};
|
||||||
static const struct intel_device_info intel_i945g_info = {
|
static const struct intel_device_info intel_i945g_info = {
|
||||||
@@ -203,6 +205,7 @@ static const struct intel_device_info intel_i945gm_info = {
|
|||||||
.has_hotplug = 1, .cursor_needs_physical = 1,
|
.has_hotplug = 1, .cursor_needs_physical = 1,
|
||||||
.has_overlay = 1, .overlay_needs_physical = 1,
|
.has_overlay = 1, .overlay_needs_physical = 1,
|
||||||
.supports_tv = 1,
|
.supports_tv = 1,
|
||||||
|
.has_fbc = 1,
|
||||||
.ring_mask = RENDER_RING,
|
.ring_mask = RENDER_RING,
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -502,6 +505,8 @@ static int i915_drm_freeze(struct drm_device *dev)
|
|||||||
struct drm_i915_private *dev_priv = dev->dev_private;
|
struct drm_i915_private *dev_priv = dev->dev_private;
|
||||||
struct drm_crtc *crtc;
|
struct drm_crtc *crtc;
|
||||||
|
|
||||||
|
intel_runtime_pm_get(dev_priv);
|
||||||
|
|
||||||
/* ignore lid events during suspend */
|
/* ignore lid events during suspend */
|
||||||
mutex_lock(&dev_priv->modeset_restore_lock);
|
mutex_lock(&dev_priv->modeset_restore_lock);
|
||||||
dev_priv->modeset_restore = MODESET_SUSPENDED;
|
dev_priv->modeset_restore = MODESET_SUSPENDED;
|
||||||
@@ -688,6 +693,8 @@ static int __i915_drm_thaw(struct drm_device *dev, bool restore_gtt_mappings)
|
|||||||
mutex_lock(&dev_priv->modeset_restore_lock);
|
mutex_lock(&dev_priv->modeset_restore_lock);
|
||||||
dev_priv->modeset_restore = MODESET_DONE;
|
dev_priv->modeset_restore = MODESET_DONE;
|
||||||
mutex_unlock(&dev_priv->modeset_restore_lock);
|
mutex_unlock(&dev_priv->modeset_restore_lock);
|
||||||
|
|
||||||
|
intel_runtime_pm_put(dev_priv);
|
||||||
return error;
|
return error;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -902,6 +909,38 @@ static int i915_pm_poweroff(struct device *dev)
|
|||||||
return i915_drm_freeze(drm_dev);
|
return i915_drm_freeze(drm_dev);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int i915_runtime_suspend(struct device *device)
|
||||||
|
{
|
||||||
|
struct pci_dev *pdev = to_pci_dev(device);
|
||||||
|
struct drm_device *dev = pci_get_drvdata(pdev);
|
||||||
|
struct drm_i915_private *dev_priv = dev->dev_private;
|
||||||
|
|
||||||
|
WARN_ON(!HAS_RUNTIME_PM(dev));
|
||||||
|
|
||||||
|
DRM_DEBUG_KMS("Suspending device\n");
|
||||||
|
|
||||||
|
dev_priv->pm.suspended = true;
|
||||||
|
intel_opregion_notify_adapter(dev, PCI_D3cold);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int i915_runtime_resume(struct device *device)
|
||||||
|
{
|
||||||
|
struct pci_dev *pdev = to_pci_dev(device);
|
||||||
|
struct drm_device *dev = pci_get_drvdata(pdev);
|
||||||
|
struct drm_i915_private *dev_priv = dev->dev_private;
|
||||||
|
|
||||||
|
WARN_ON(!HAS_RUNTIME_PM(dev));
|
||||||
|
|
||||||
|
DRM_DEBUG_KMS("Resuming device\n");
|
||||||
|
|
||||||
|
intel_opregion_notify_adapter(dev, PCI_D0);
|
||||||
|
dev_priv->pm.suspended = false;
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
static const struct dev_pm_ops i915_pm_ops = {
|
static const struct dev_pm_ops i915_pm_ops = {
|
||||||
.suspend = i915_pm_suspend,
|
.suspend = i915_pm_suspend,
|
||||||
.resume = i915_pm_resume,
|
.resume = i915_pm_resume,
|
||||||
@@ -909,6 +948,8 @@ static const struct dev_pm_ops i915_pm_ops = {
|
|||||||
.thaw = i915_pm_thaw,
|
.thaw = i915_pm_thaw,
|
||||||
.poweroff = i915_pm_poweroff,
|
.poweroff = i915_pm_poweroff,
|
||||||
.restore = i915_pm_resume,
|
.restore = i915_pm_resume,
|
||||||
|
.runtime_suspend = i915_runtime_suspend,
|
||||||
|
.runtime_resume = i915_runtime_resume,
|
||||||
};
|
};
|
||||||
|
|
||||||
static const struct vm_operations_struct i915_gem_vm_ops = {
|
static const struct vm_operations_struct i915_gem_vm_ops = {
|
||||||
|
@@ -323,7 +323,7 @@ struct drm_i915_error_state {
|
|||||||
u32 instps[I915_NUM_RINGS];
|
u32 instps[I915_NUM_RINGS];
|
||||||
u32 extra_instdone[I915_NUM_INSTDONE_REG];
|
u32 extra_instdone[I915_NUM_INSTDONE_REG];
|
||||||
u32 seqno[I915_NUM_RINGS];
|
u32 seqno[I915_NUM_RINGS];
|
||||||
u64 bbaddr;
|
u64 bbaddr[I915_NUM_RINGS];
|
||||||
u32 fault_reg[I915_NUM_RINGS];
|
u32 fault_reg[I915_NUM_RINGS];
|
||||||
u32 done_reg;
|
u32 done_reg;
|
||||||
u32 faddr[I915_NUM_RINGS];
|
u32 faddr[I915_NUM_RINGS];
|
||||||
@@ -372,7 +372,7 @@ struct dpll;
|
|||||||
|
|
||||||
struct drm_i915_display_funcs {
|
struct drm_i915_display_funcs {
|
||||||
bool (*fbc_enabled)(struct drm_device *dev);
|
bool (*fbc_enabled)(struct drm_device *dev);
|
||||||
void (*enable_fbc)(struct drm_crtc *crtc, unsigned long interval);
|
void (*enable_fbc)(struct drm_crtc *crtc);
|
||||||
void (*disable_fbc)(struct drm_device *dev);
|
void (*disable_fbc)(struct drm_device *dev);
|
||||||
int (*get_display_clock_speed)(struct drm_device *dev);
|
int (*get_display_clock_speed)(struct drm_device *dev);
|
||||||
int (*get_fifo_size)(struct drm_device *dev, int plane);
|
int (*get_fifo_size)(struct drm_device *dev, int plane);
|
||||||
@@ -695,7 +695,6 @@ struct i915_fbc {
|
|||||||
struct delayed_work work;
|
struct delayed_work work;
|
||||||
struct drm_crtc *crtc;
|
struct drm_crtc *crtc;
|
||||||
struct drm_framebuffer *fb;
|
struct drm_framebuffer *fb;
|
||||||
int interval;
|
|
||||||
} *fbc_work;
|
} *fbc_work;
|
||||||
|
|
||||||
enum no_fbc_reason {
|
enum no_fbc_reason {
|
||||||
@@ -1289,6 +1288,10 @@ struct i915_package_c8 {
|
|||||||
} regsave;
|
} regsave;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct i915_runtime_pm {
|
||||||
|
bool suspended;
|
||||||
|
};
|
||||||
|
|
||||||
enum intel_pipe_crc_source {
|
enum intel_pipe_crc_source {
|
||||||
INTEL_PIPE_CRC_SOURCE_NONE,
|
INTEL_PIPE_CRC_SOURCE_NONE,
|
||||||
INTEL_PIPE_CRC_SOURCE_PLANE1,
|
INTEL_PIPE_CRC_SOURCE_PLANE1,
|
||||||
@@ -1519,6 +1522,8 @@ typedef struct drm_i915_private {
|
|||||||
|
|
||||||
struct i915_package_c8 pc8;
|
struct i915_package_c8 pc8;
|
||||||
|
|
||||||
|
struct i915_runtime_pm pm;
|
||||||
|
|
||||||
/* Old dri1 support infrastructure, beware the dragons ya fools entering
|
/* Old dri1 support infrastructure, beware the dragons ya fools entering
|
||||||
* here! */
|
* here! */
|
||||||
struct i915_dri1_state dri1;
|
struct i915_dri1_state dri1;
|
||||||
@@ -1843,6 +1848,7 @@ struct drm_i915_file_private {
|
|||||||
#define HAS_FPGA_DBG_UNCLAIMED(dev) (INTEL_INFO(dev)->has_fpga_dbg)
|
#define HAS_FPGA_DBG_UNCLAIMED(dev) (INTEL_INFO(dev)->has_fpga_dbg)
|
||||||
#define HAS_PSR(dev) (IS_HASWELL(dev) || IS_BROADWELL(dev))
|
#define HAS_PSR(dev) (IS_HASWELL(dev) || IS_BROADWELL(dev))
|
||||||
#define HAS_PC8(dev) (IS_HASWELL(dev)) /* XXX HSW:ULX */
|
#define HAS_PC8(dev) (IS_HASWELL(dev)) /* XXX HSW:ULX */
|
||||||
|
#define HAS_RUNTIME_PM(dev) false
|
||||||
|
|
||||||
#define INTEL_PCH_DEVICE_ID_MASK 0xff00
|
#define INTEL_PCH_DEVICE_ID_MASK 0xff00
|
||||||
#define INTEL_PCH_IBX_DEVICE_ID_TYPE 0x3b00
|
#define INTEL_PCH_IBX_DEVICE_ID_TYPE 0x3b00
|
||||||
@@ -2468,6 +2474,8 @@ u32 intel_sbi_read(struct drm_i915_private *dev_priv, u16 reg,
|
|||||||
enum intel_sbi_destination destination);
|
enum intel_sbi_destination destination);
|
||||||
void intel_sbi_write(struct drm_i915_private *dev_priv, u16 reg, u32 value,
|
void intel_sbi_write(struct drm_i915_private *dev_priv, u16 reg, u32 value,
|
||||||
enum intel_sbi_destination destination);
|
enum intel_sbi_destination destination);
|
||||||
|
u32 vlv_flisdsi_read(struct drm_i915_private *dev_priv, u32 reg);
|
||||||
|
void vlv_flisdsi_write(struct drm_i915_private *dev_priv, u32 reg, u32 val);
|
||||||
|
|
||||||
int vlv_gpu_freq(struct drm_i915_private *dev_priv, int val);
|
int vlv_gpu_freq(struct drm_i915_private *dev_priv, int val);
|
||||||
int vlv_freq_opcode(struct drm_i915_private *dev_priv, int val);
|
int vlv_freq_opcode(struct drm_i915_private *dev_priv, int val);
|
||||||
|
@@ -1015,9 +1015,11 @@ static int __wait_seqno(struct intel_ring_buffer *ring, u32 seqno,
|
|||||||
struct drm_i915_file_private *file_priv)
|
struct drm_i915_file_private *file_priv)
|
||||||
{
|
{
|
||||||
drm_i915_private_t *dev_priv = ring->dev->dev_private;
|
drm_i915_private_t *dev_priv = ring->dev->dev_private;
|
||||||
|
const bool irq_test_in_progress =
|
||||||
|
ACCESS_ONCE(dev_priv->gpu_error.test_irq_rings) & intel_ring_flag(ring);
|
||||||
struct timespec before, now;
|
struct timespec before, now;
|
||||||
DEFINE_WAIT(wait);
|
DEFINE_WAIT(wait);
|
||||||
long timeout_jiffies;
|
unsigned long timeout_expire;
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
WARN(dev_priv->pc8.irqs_disabled, "IRQs disabled\n");
|
WARN(dev_priv->pc8.irqs_disabled, "IRQs disabled\n");
|
||||||
@@ -1025,7 +1027,7 @@ static int __wait_seqno(struct intel_ring_buffer *ring, u32 seqno,
|
|||||||
if (i915_seqno_passed(ring->get_seqno(ring, true), seqno))
|
if (i915_seqno_passed(ring->get_seqno(ring, true), seqno))
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
timeout_jiffies = timeout ? timespec_to_jiffies_timeout(timeout) : 1;
|
timeout_expire = timeout ? jiffies + timespec_to_jiffies_timeout(timeout) : 0;
|
||||||
|
|
||||||
if (dev_priv->info->gen >= 6 && can_wait_boost(file_priv)) {
|
if (dev_priv->info->gen >= 6 && can_wait_boost(file_priv)) {
|
||||||
gen6_rps_boost(dev_priv);
|
gen6_rps_boost(dev_priv);
|
||||||
@@ -1035,8 +1037,7 @@ static int __wait_seqno(struct intel_ring_buffer *ring, u32 seqno,
|
|||||||
msecs_to_jiffies(100));
|
msecs_to_jiffies(100));
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!(dev_priv->gpu_error.test_irq_rings & intel_ring_flag(ring)) &&
|
if (!irq_test_in_progress && WARN_ON(!ring->irq_get(ring)))
|
||||||
WARN_ON(!ring->irq_get(ring)))
|
|
||||||
return -ENODEV;
|
return -ENODEV;
|
||||||
|
|
||||||
/* Record current time in case interrupted by signal, or wedged */
|
/* Record current time in case interrupted by signal, or wedged */
|
||||||
@@ -1044,7 +1045,6 @@ static int __wait_seqno(struct intel_ring_buffer *ring, u32 seqno,
|
|||||||
getrawmonotonic(&before);
|
getrawmonotonic(&before);
|
||||||
for (;;) {
|
for (;;) {
|
||||||
struct timer_list timer;
|
struct timer_list timer;
|
||||||
unsigned long expire;
|
|
||||||
|
|
||||||
prepare_to_wait(&ring->irq_queue, &wait,
|
prepare_to_wait(&ring->irq_queue, &wait,
|
||||||
interruptible ? TASK_INTERRUPTIBLE : TASK_UNINTERRUPTIBLE);
|
interruptible ? TASK_INTERRUPTIBLE : TASK_UNINTERRUPTIBLE);
|
||||||
@@ -1070,23 +1070,22 @@ static int __wait_seqno(struct intel_ring_buffer *ring, u32 seqno,
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (timeout_jiffies <= 0) {
|
if (timeout && time_after_eq(jiffies, timeout_expire)) {
|
||||||
ret = -ETIME;
|
ret = -ETIME;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
timer.function = NULL;
|
timer.function = NULL;
|
||||||
if (timeout || missed_irq(dev_priv, ring)) {
|
if (timeout || missed_irq(dev_priv, ring)) {
|
||||||
|
unsigned long expire;
|
||||||
|
|
||||||
setup_timer_on_stack(&timer, fake_irq, (unsigned long)current);
|
setup_timer_on_stack(&timer, fake_irq, (unsigned long)current);
|
||||||
expire = jiffies + (missed_irq(dev_priv, ring) ? 1: timeout_jiffies);
|
expire = missed_irq(dev_priv, ring) ? jiffies + 1 : timeout_expire;
|
||||||
mod_timer(&timer, expire);
|
mod_timer(&timer, expire);
|
||||||
}
|
}
|
||||||
|
|
||||||
io_schedule();
|
io_schedule();
|
||||||
|
|
||||||
if (timeout)
|
|
||||||
timeout_jiffies = expire - jiffies;
|
|
||||||
|
|
||||||
if (timer.function) {
|
if (timer.function) {
|
||||||
del_singleshot_timer_sync(&timer);
|
del_singleshot_timer_sync(&timer);
|
||||||
destroy_timer_on_stack(&timer);
|
destroy_timer_on_stack(&timer);
|
||||||
@@ -1095,7 +1094,8 @@ static int __wait_seqno(struct intel_ring_buffer *ring, u32 seqno,
|
|||||||
getrawmonotonic(&now);
|
getrawmonotonic(&now);
|
||||||
trace_i915_gem_request_wait_end(ring, seqno);
|
trace_i915_gem_request_wait_end(ring, seqno);
|
||||||
|
|
||||||
ring->irq_put(ring);
|
if (!irq_test_in_progress)
|
||||||
|
ring->irq_put(ring);
|
||||||
|
|
||||||
finish_wait(&ring->irq_queue, &wait);
|
finish_wait(&ring->irq_queue, &wait);
|
||||||
|
|
||||||
@@ -1380,6 +1380,8 @@ int i915_gem_fault(struct vm_area_struct *vma, struct vm_fault *vmf)
|
|||||||
int ret = 0;
|
int ret = 0;
|
||||||
bool write = !!(vmf->flags & FAULT_FLAG_WRITE);
|
bool write = !!(vmf->flags & FAULT_FLAG_WRITE);
|
||||||
|
|
||||||
|
intel_runtime_pm_get(dev_priv);
|
||||||
|
|
||||||
/* We don't use vmf->pgoff since that has the fake offset */
|
/* We don't use vmf->pgoff since that has the fake offset */
|
||||||
page_offset = ((unsigned long)vmf->virtual_address - vma->vm_start) >>
|
page_offset = ((unsigned long)vmf->virtual_address - vma->vm_start) >>
|
||||||
PAGE_SHIFT;
|
PAGE_SHIFT;
|
||||||
@@ -1427,8 +1429,10 @@ out:
|
|||||||
/* If this -EIO is due to a gpu hang, give the reset code a
|
/* If this -EIO is due to a gpu hang, give the reset code a
|
||||||
* chance to clean up the mess. Otherwise return the proper
|
* chance to clean up the mess. Otherwise return the proper
|
||||||
* SIGBUS. */
|
* SIGBUS. */
|
||||||
if (i915_terminally_wedged(&dev_priv->gpu_error))
|
if (i915_terminally_wedged(&dev_priv->gpu_error)) {
|
||||||
return VM_FAULT_SIGBUS;
|
ret = VM_FAULT_SIGBUS;
|
||||||
|
break;
|
||||||
|
}
|
||||||
case -EAGAIN:
|
case -EAGAIN:
|
||||||
/*
|
/*
|
||||||
* EAGAIN means the gpu is hung and we'll wait for the error
|
* EAGAIN means the gpu is hung and we'll wait for the error
|
||||||
@@ -1443,15 +1447,22 @@ out:
|
|||||||
* EBUSY is ok: this just means that another thread
|
* EBUSY is ok: this just means that another thread
|
||||||
* already did the job.
|
* already did the job.
|
||||||
*/
|
*/
|
||||||
return VM_FAULT_NOPAGE;
|
ret = VM_FAULT_NOPAGE;
|
||||||
|
break;
|
||||||
case -ENOMEM:
|
case -ENOMEM:
|
||||||
return VM_FAULT_OOM;
|
ret = VM_FAULT_OOM;
|
||||||
|
break;
|
||||||
case -ENOSPC:
|
case -ENOSPC:
|
||||||
return VM_FAULT_SIGBUS;
|
ret = VM_FAULT_SIGBUS;
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
WARN_ONCE(ret, "unhandled error in i915_gem_fault: %i\n", ret);
|
WARN_ONCE(ret, "unhandled error in i915_gem_fault: %i\n", ret);
|
||||||
return VM_FAULT_SIGBUS;
|
ret = VM_FAULT_SIGBUS;
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
intel_runtime_pm_put(dev_priv);
|
||||||
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -2746,7 +2757,6 @@ int i915_vma_unbind(struct i915_vma *vma)
|
|||||||
obj->has_aliasing_ppgtt_mapping = 0;
|
obj->has_aliasing_ppgtt_mapping = 0;
|
||||||
}
|
}
|
||||||
i915_gem_gtt_finish_object(obj);
|
i915_gem_gtt_finish_object(obj);
|
||||||
i915_gem_object_unpin_pages(obj);
|
|
||||||
|
|
||||||
list_del(&vma->mm_list);
|
list_del(&vma->mm_list);
|
||||||
/* Avoid an unnecessary call to unbind on rebind. */
|
/* Avoid an unnecessary call to unbind on rebind. */
|
||||||
@@ -2754,7 +2764,6 @@ int i915_vma_unbind(struct i915_vma *vma)
|
|||||||
obj->map_and_fenceable = true;
|
obj->map_and_fenceable = true;
|
||||||
|
|
||||||
drm_mm_remove_node(&vma->node);
|
drm_mm_remove_node(&vma->node);
|
||||||
|
|
||||||
i915_gem_vma_destroy(vma);
|
i915_gem_vma_destroy(vma);
|
||||||
|
|
||||||
/* Since the unbound list is global, only move to that list if
|
/* Since the unbound list is global, only move to that list if
|
||||||
@@ -2762,6 +2771,12 @@ int i915_vma_unbind(struct i915_vma *vma)
|
|||||||
if (list_empty(&obj->vma_list))
|
if (list_empty(&obj->vma_list))
|
||||||
list_move_tail(&obj->global_list, &dev_priv->mm.unbound_list);
|
list_move_tail(&obj->global_list, &dev_priv->mm.unbound_list);
|
||||||
|
|
||||||
|
/* And finally now the object is completely decoupled from this vma,
|
||||||
|
* we can drop its hold on the backing storage and allow it to be
|
||||||
|
* reaped by the shrinker.
|
||||||
|
*/
|
||||||
|
i915_gem_object_unpin_pages(obj);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -4165,6 +4180,8 @@ void i915_gem_free_object(struct drm_gem_object *gem_obj)
|
|||||||
drm_i915_private_t *dev_priv = dev->dev_private;
|
drm_i915_private_t *dev_priv = dev->dev_private;
|
||||||
struct i915_vma *vma, *next;
|
struct i915_vma *vma, *next;
|
||||||
|
|
||||||
|
intel_runtime_pm_get(dev_priv);
|
||||||
|
|
||||||
trace_i915_gem_object_destroy(obj);
|
trace_i915_gem_object_destroy(obj);
|
||||||
|
|
||||||
if (obj->phys_obj)
|
if (obj->phys_obj)
|
||||||
@@ -4209,6 +4226,8 @@ void i915_gem_free_object(struct drm_gem_object *gem_obj)
|
|||||||
|
|
||||||
kfree(obj->bit_17);
|
kfree(obj->bit_17);
|
||||||
i915_gem_object_free(obj);
|
i915_gem_object_free(obj);
|
||||||
|
|
||||||
|
intel_runtime_pm_put(dev_priv);
|
||||||
}
|
}
|
||||||
|
|
||||||
struct i915_vma *i915_gem_obj_to_vma(struct drm_i915_gem_object *obj,
|
struct i915_vma *i915_gem_obj_to_vma(struct drm_i915_gem_object *obj,
|
||||||
|
@@ -888,6 +888,24 @@ validate_exec_list(struct drm_i915_gem_exec_object2 *exec,
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
i915_gem_validate_context(struct drm_device *dev, struct drm_file *file,
|
||||||
|
const u32 ctx_id)
|
||||||
|
{
|
||||||
|
struct i915_ctx_hang_stats *hs;
|
||||||
|
|
||||||
|
hs = i915_gem_context_get_hang_stats(dev, file, ctx_id);
|
||||||
|
if (IS_ERR(hs))
|
||||||
|
return PTR_ERR(hs);
|
||||||
|
|
||||||
|
if (hs->banned) {
|
||||||
|
DRM_DEBUG("Context %u tried to submit while banned\n", ctx_id);
|
||||||
|
return -EIO;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
i915_gem_execbuffer_move_to_active(struct list_head *vmas,
|
i915_gem_execbuffer_move_to_active(struct list_head *vmas,
|
||||||
struct intel_ring_buffer *ring)
|
struct intel_ring_buffer *ring)
|
||||||
@@ -967,8 +985,7 @@ i915_gem_do_execbuffer(struct drm_device *dev, void *data,
|
|||||||
struct drm_i915_gem_object *batch_obj;
|
struct drm_i915_gem_object *batch_obj;
|
||||||
struct drm_clip_rect *cliprects = NULL;
|
struct drm_clip_rect *cliprects = NULL;
|
||||||
struct intel_ring_buffer *ring;
|
struct intel_ring_buffer *ring;
|
||||||
struct i915_ctx_hang_stats *hs;
|
const u32 ctx_id = i915_execbuffer2_get_context_id(*args);
|
||||||
u32 ctx_id = i915_execbuffer2_get_context_id(*args);
|
|
||||||
u32 exec_start, exec_len;
|
u32 exec_start, exec_len;
|
||||||
u32 mask, flags;
|
u32 mask, flags;
|
||||||
int ret, mode, i;
|
int ret, mode, i;
|
||||||
@@ -1095,6 +1112,8 @@ i915_gem_do_execbuffer(struct drm_device *dev, void *data,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
intel_runtime_pm_get(dev_priv);
|
||||||
|
|
||||||
ret = i915_mutex_lock_interruptible(dev);
|
ret = i915_mutex_lock_interruptible(dev);
|
||||||
if (ret)
|
if (ret)
|
||||||
goto pre_mutex_err;
|
goto pre_mutex_err;
|
||||||
@@ -1105,6 +1124,12 @@ i915_gem_do_execbuffer(struct drm_device *dev, void *data,
|
|||||||
goto pre_mutex_err;
|
goto pre_mutex_err;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ret = i915_gem_validate_context(dev, file, ctx_id);
|
||||||
|
if (ret) {
|
||||||
|
mutex_unlock(&dev->struct_mutex);
|
||||||
|
goto pre_mutex_err;
|
||||||
|
}
|
||||||
|
|
||||||
eb = eb_create(args);
|
eb = eb_create(args);
|
||||||
if (eb == NULL) {
|
if (eb == NULL) {
|
||||||
mutex_unlock(&dev->struct_mutex);
|
mutex_unlock(&dev->struct_mutex);
|
||||||
@@ -1157,17 +1182,6 @@ i915_gem_do_execbuffer(struct drm_device *dev, void *data,
|
|||||||
if (ret)
|
if (ret)
|
||||||
goto err;
|
goto err;
|
||||||
|
|
||||||
hs = i915_gem_context_get_hang_stats(dev, file, ctx_id);
|
|
||||||
if (IS_ERR(hs)) {
|
|
||||||
ret = PTR_ERR(hs);
|
|
||||||
goto err;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (hs->banned) {
|
|
||||||
ret = -EIO;
|
|
||||||
goto err;
|
|
||||||
}
|
|
||||||
|
|
||||||
ret = i915_switch_context(ring, file, ctx_id);
|
ret = i915_switch_context(ring, file, ctx_id);
|
||||||
if (ret)
|
if (ret)
|
||||||
goto err;
|
goto err;
|
||||||
@@ -1229,6 +1243,10 @@ err:
|
|||||||
|
|
||||||
pre_mutex_err:
|
pre_mutex_err:
|
||||||
kfree(cliprects);
|
kfree(cliprects);
|
||||||
|
|
||||||
|
/* intel_gpu_busy should also get a ref, so it will free when the device
|
||||||
|
* is really idle. */
|
||||||
|
intel_runtime_pm_put(dev_priv);
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -247,12 +247,11 @@ static void i915_ring_error_state(struct drm_i915_error_state_buf *m,
|
|||||||
err_printf(m, " IPEIR: 0x%08x\n", error->ipeir[ring]);
|
err_printf(m, " IPEIR: 0x%08x\n", error->ipeir[ring]);
|
||||||
err_printf(m, " IPEHR: 0x%08x\n", error->ipehr[ring]);
|
err_printf(m, " IPEHR: 0x%08x\n", error->ipehr[ring]);
|
||||||
err_printf(m, " INSTDONE: 0x%08x\n", error->instdone[ring]);
|
err_printf(m, " INSTDONE: 0x%08x\n", error->instdone[ring]);
|
||||||
if (ring == RCS && INTEL_INFO(dev)->gen >= 4)
|
if (INTEL_INFO(dev)->gen >= 4) {
|
||||||
err_printf(m, " BBADDR: 0x%08llx\n", error->bbaddr);
|
err_printf(m, " BBADDR: 0x%08llx\n", error->bbaddr[ring]);
|
||||||
if (INTEL_INFO(dev)->gen >= 4)
|
|
||||||
err_printf(m, " BB_STATE: 0x%08x\n", error->bbstate[ring]);
|
err_printf(m, " BB_STATE: 0x%08x\n", error->bbstate[ring]);
|
||||||
if (INTEL_INFO(dev)->gen >= 4)
|
|
||||||
err_printf(m, " INSTPS: 0x%08x\n", error->instps[ring]);
|
err_printf(m, " INSTPS: 0x%08x\n", error->instps[ring]);
|
||||||
|
}
|
||||||
err_printf(m, " INSTPM: 0x%08x\n", error->instpm[ring]);
|
err_printf(m, " INSTPM: 0x%08x\n", error->instpm[ring]);
|
||||||
err_printf(m, " FADDR: 0x%08x\n", error->faddr[ring]);
|
err_printf(m, " FADDR: 0x%08x\n", error->faddr[ring]);
|
||||||
if (INTEL_INFO(dev)->gen >= 6) {
|
if (INTEL_INFO(dev)->gen >= 6) {
|
||||||
@@ -725,8 +724,9 @@ static void i915_record_ring_state(struct drm_device *dev,
|
|||||||
error->ipehr[ring->id] = I915_READ(RING_IPEHR(ring->mmio_base));
|
error->ipehr[ring->id] = I915_READ(RING_IPEHR(ring->mmio_base));
|
||||||
error->instdone[ring->id] = I915_READ(RING_INSTDONE(ring->mmio_base));
|
error->instdone[ring->id] = I915_READ(RING_INSTDONE(ring->mmio_base));
|
||||||
error->instps[ring->id] = I915_READ(RING_INSTPS(ring->mmio_base));
|
error->instps[ring->id] = I915_READ(RING_INSTPS(ring->mmio_base));
|
||||||
if (ring->id == RCS)
|
error->bbaddr[ring->id] = I915_READ(RING_BBADDR(ring->mmio_base));
|
||||||
error->bbaddr = I915_READ64(BB_ADDR);
|
if (INTEL_INFO(dev)->gen >= 8)
|
||||||
|
error->bbaddr[ring->id] |= (u64) I915_READ(RING_BBADDR_UDW(ring->mmio_base)) << 32;
|
||||||
error->bbstate[ring->id] = I915_READ(RING_BBSTATE(ring->mmio_base));
|
error->bbstate[ring->id] = I915_READ(RING_BBSTATE(ring->mmio_base));
|
||||||
} else {
|
} else {
|
||||||
error->faddr[ring->id] = I915_READ(DMA_FADD_I8XX);
|
error->faddr[ring->id] = I915_READ(DMA_FADD_I8XX);
|
||||||
|
@@ -3139,10 +3139,10 @@ static int i8xx_irq_postinstall(struct drm_device *dev)
|
|||||||
* Returns true when a page flip has completed.
|
* Returns true when a page flip has completed.
|
||||||
*/
|
*/
|
||||||
static bool i8xx_handle_vblank(struct drm_device *dev,
|
static bool i8xx_handle_vblank(struct drm_device *dev,
|
||||||
int pipe, u16 iir)
|
int plane, int pipe, u32 iir)
|
||||||
{
|
{
|
||||||
drm_i915_private_t *dev_priv = dev->dev_private;
|
drm_i915_private_t *dev_priv = dev->dev_private;
|
||||||
u16 flip_pending = DISPLAY_PLANE_FLIP_PENDING(pipe);
|
u16 flip_pending = DISPLAY_PLANE_FLIP_PENDING(plane);
|
||||||
|
|
||||||
if (!drm_handle_vblank(dev, pipe))
|
if (!drm_handle_vblank(dev, pipe))
|
||||||
return false;
|
return false;
|
||||||
@@ -3150,7 +3150,7 @@ static bool i8xx_handle_vblank(struct drm_device *dev,
|
|||||||
if ((iir & flip_pending) == 0)
|
if ((iir & flip_pending) == 0)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
intel_prepare_page_flip(dev, pipe);
|
intel_prepare_page_flip(dev, plane);
|
||||||
|
|
||||||
/* We detect FlipDone by looking for the change in PendingFlip from '1'
|
/* We detect FlipDone by looking for the change in PendingFlip from '1'
|
||||||
* to '0' on the following vblank, i.e. IIR has the Pendingflip
|
* to '0' on the following vblank, i.e. IIR has the Pendingflip
|
||||||
@@ -3219,9 +3219,13 @@ static irqreturn_t i8xx_irq_handler(int irq, void *arg)
|
|||||||
notify_ring(dev, &dev_priv->ring[RCS]);
|
notify_ring(dev, &dev_priv->ring[RCS]);
|
||||||
|
|
||||||
for_each_pipe(pipe) {
|
for_each_pipe(pipe) {
|
||||||
|
int plane = pipe;
|
||||||
|
if (IS_MOBILE(dev))
|
||||||
|
plane = !plane;
|
||||||
|
|
||||||
if (pipe_stats[pipe] & PIPE_VBLANK_INTERRUPT_STATUS &&
|
if (pipe_stats[pipe] & PIPE_VBLANK_INTERRUPT_STATUS &&
|
||||||
i8xx_handle_vblank(dev, pipe, iir))
|
i8xx_handle_vblank(dev, plane, pipe, iir))
|
||||||
flip_mask &= ~DISPLAY_PLANE_FLIP_PENDING(pipe);
|
flip_mask &= ~DISPLAY_PLANE_FLIP_PENDING(plane);
|
||||||
|
|
||||||
if (pipe_stats[pipe] & PIPE_CRC_DONE_INTERRUPT_STATUS)
|
if (pipe_stats[pipe] & PIPE_CRC_DONE_INTERRUPT_STATUS)
|
||||||
i9xx_pipe_crc_irq_handler(dev, pipe);
|
i9xx_pipe_crc_irq_handler(dev, pipe);
|
||||||
@@ -3896,8 +3900,8 @@ void hsw_pc8_disable_interrupts(struct drm_device *dev)
|
|||||||
dev_priv->pc8.regsave.gtier = I915_READ(GTIER);
|
dev_priv->pc8.regsave.gtier = I915_READ(GTIER);
|
||||||
dev_priv->pc8.regsave.gen6_pmimr = I915_READ(GEN6_PMIMR);
|
dev_priv->pc8.regsave.gen6_pmimr = I915_READ(GEN6_PMIMR);
|
||||||
|
|
||||||
ironlake_disable_display_irq(dev_priv, ~DE_PCH_EVENT_IVB);
|
ironlake_disable_display_irq(dev_priv, 0xffffffff);
|
||||||
ibx_disable_display_interrupt(dev_priv, ~SDE_HOTPLUG_MASK_CPT);
|
ibx_disable_display_interrupt(dev_priv, 0xffffffff);
|
||||||
ilk_disable_gt_irq(dev_priv, 0xffffffff);
|
ilk_disable_gt_irq(dev_priv, 0xffffffff);
|
||||||
snb_disable_pm_irq(dev_priv, 0xffffffff);
|
snb_disable_pm_irq(dev_priv, 0xffffffff);
|
||||||
|
|
||||||
@@ -3911,34 +3915,26 @@ void hsw_pc8_restore_interrupts(struct drm_device *dev)
|
|||||||
{
|
{
|
||||||
struct drm_i915_private *dev_priv = dev->dev_private;
|
struct drm_i915_private *dev_priv = dev->dev_private;
|
||||||
unsigned long irqflags;
|
unsigned long irqflags;
|
||||||
uint32_t val, expected;
|
uint32_t val;
|
||||||
|
|
||||||
spin_lock_irqsave(&dev_priv->irq_lock, irqflags);
|
spin_lock_irqsave(&dev_priv->irq_lock, irqflags);
|
||||||
|
|
||||||
val = I915_READ(DEIMR);
|
val = I915_READ(DEIMR);
|
||||||
expected = ~DE_PCH_EVENT_IVB;
|
WARN(val != 0xffffffff, "DEIMR is 0x%08x\n", val);
|
||||||
WARN(val != expected, "DEIMR is 0x%08x, not 0x%08x\n", val, expected);
|
|
||||||
|
|
||||||
val = I915_READ(SDEIMR) & ~SDE_HOTPLUG_MASK_CPT;
|
val = I915_READ(SDEIMR);
|
||||||
expected = ~SDE_HOTPLUG_MASK_CPT;
|
WARN(val != 0xffffffff, "SDEIMR is 0x%08x\n", val);
|
||||||
WARN(val != expected, "SDEIMR non-HPD bits are 0x%08x, not 0x%08x\n",
|
|
||||||
val, expected);
|
|
||||||
|
|
||||||
val = I915_READ(GTIMR);
|
val = I915_READ(GTIMR);
|
||||||
expected = 0xffffffff;
|
WARN(val != 0xffffffff, "GTIMR is 0x%08x\n", val);
|
||||||
WARN(val != expected, "GTIMR is 0x%08x, not 0x%08x\n", val, expected);
|
|
||||||
|
|
||||||
val = I915_READ(GEN6_PMIMR);
|
val = I915_READ(GEN6_PMIMR);
|
||||||
expected = 0xffffffff;
|
WARN(val != 0xffffffff, "GEN6_PMIMR is 0x%08x\n", val);
|
||||||
WARN(val != expected, "GEN6_PMIMR is 0x%08x, not 0x%08x\n", val,
|
|
||||||
expected);
|
|
||||||
|
|
||||||
dev_priv->pc8.irqs_disabled = false;
|
dev_priv->pc8.irqs_disabled = false;
|
||||||
|
|
||||||
ironlake_enable_display_irq(dev_priv, ~dev_priv->pc8.regsave.deimr);
|
ironlake_enable_display_irq(dev_priv, ~dev_priv->pc8.regsave.deimr);
|
||||||
ibx_enable_display_interrupt(dev_priv,
|
ibx_enable_display_interrupt(dev_priv, ~dev_priv->pc8.regsave.sdeimr);
|
||||||
~dev_priv->pc8.regsave.sdeimr &
|
|
||||||
~SDE_HOTPLUG_MASK_CPT);
|
|
||||||
ilk_enable_gt_irq(dev_priv, ~dev_priv->pc8.regsave.gtimr);
|
ilk_enable_gt_irq(dev_priv, ~dev_priv->pc8.regsave.gtimr);
|
||||||
snb_enable_pm_irq(dev_priv, ~dev_priv->pc8.regsave.gen6_pmimr);
|
snb_enable_pm_irq(dev_priv, ~dev_priv->pc8.regsave.gen6_pmimr);
|
||||||
I915_WRITE(GTIER, dev_priv->pc8.regsave.gtier);
|
I915_WRITE(GTIER, dev_priv->pc8.regsave.gtier);
|
||||||
|
@@ -362,6 +362,7 @@
|
|||||||
#define IOSF_PORT_CCK 0x14
|
#define IOSF_PORT_CCK 0x14
|
||||||
#define IOSF_PORT_CCU 0xA9
|
#define IOSF_PORT_CCU 0xA9
|
||||||
#define IOSF_PORT_GPS_CORE 0x48
|
#define IOSF_PORT_GPS_CORE 0x48
|
||||||
|
#define IOSF_PORT_FLISDSI 0x1B
|
||||||
#define VLV_IOSF_DATA (VLV_DISPLAY_BASE + 0x2104)
|
#define VLV_IOSF_DATA (VLV_DISPLAY_BASE + 0x2104)
|
||||||
#define VLV_IOSF_ADDR (VLV_DISPLAY_BASE + 0x2108)
|
#define VLV_IOSF_ADDR (VLV_DISPLAY_BASE + 0x2108)
|
||||||
|
|
||||||
@@ -734,6 +735,8 @@
|
|||||||
#define HWSTAM 0x02098
|
#define HWSTAM 0x02098
|
||||||
#define DMA_FADD_I8XX 0x020d0
|
#define DMA_FADD_I8XX 0x020d0
|
||||||
#define RING_BBSTATE(base) ((base)+0x110)
|
#define RING_BBSTATE(base) ((base)+0x110)
|
||||||
|
#define RING_BBADDR(base) ((base)+0x140)
|
||||||
|
#define RING_BBADDR_UDW(base) ((base)+0x168) /* gen8+ */
|
||||||
|
|
||||||
#define ERROR_GEN6 0x040a0
|
#define ERROR_GEN6 0x040a0
|
||||||
#define GEN7_ERR_INT 0x44040
|
#define GEN7_ERR_INT 0x44040
|
||||||
@@ -924,7 +927,6 @@
|
|||||||
#define CM0_COLOR_EVICT_DISABLE (1<<3)
|
#define CM0_COLOR_EVICT_DISABLE (1<<3)
|
||||||
#define CM0_DEPTH_WRITE_DISABLE (1<<1)
|
#define CM0_DEPTH_WRITE_DISABLE (1<<1)
|
||||||
#define CM0_RC_OP_FLUSH_DISABLE (1<<0)
|
#define CM0_RC_OP_FLUSH_DISABLE (1<<0)
|
||||||
#define BB_ADDR 0x02140 /* 8 bytes */
|
|
||||||
#define GFX_FLSH_CNTL 0x02170 /* 915+ only */
|
#define GFX_FLSH_CNTL 0x02170 /* 915+ only */
|
||||||
#define GFX_FLSH_CNTL_GEN6 0x101008
|
#define GFX_FLSH_CNTL_GEN6 0x101008
|
||||||
#define GFX_FLSH_CNTL_EN (1<<0)
|
#define GFX_FLSH_CNTL_EN (1<<0)
|
||||||
@@ -1001,6 +1003,7 @@
|
|||||||
|
|
||||||
#define GEN7_FF_THREAD_MODE 0x20a0
|
#define GEN7_FF_THREAD_MODE 0x20a0
|
||||||
#define GEN7_FF_SCHED_MASK 0x0077070
|
#define GEN7_FF_SCHED_MASK 0x0077070
|
||||||
|
#define GEN8_FF_DS_REF_CNT_FFME (1 << 19)
|
||||||
#define GEN7_FF_TS_SCHED_HS1 (0x5<<16)
|
#define GEN7_FF_TS_SCHED_HS1 (0x5<<16)
|
||||||
#define GEN7_FF_TS_SCHED_HS0 (0x3<<16)
|
#define GEN7_FF_TS_SCHED_HS0 (0x3<<16)
|
||||||
#define GEN7_FF_TS_SCHED_LOAD_BALANCE (0x1<<16)
|
#define GEN7_FF_TS_SCHED_LOAD_BALANCE (0x1<<16)
|
||||||
@@ -1028,14 +1031,14 @@
|
|||||||
#define FBC_CTL_UNCOMPRESSIBLE (1<<14)
|
#define FBC_CTL_UNCOMPRESSIBLE (1<<14)
|
||||||
#define FBC_CTL_C3_IDLE (1<<13)
|
#define FBC_CTL_C3_IDLE (1<<13)
|
||||||
#define FBC_CTL_STRIDE_SHIFT (5)
|
#define FBC_CTL_STRIDE_SHIFT (5)
|
||||||
#define FBC_CTL_FENCENO (1<<0)
|
#define FBC_CTL_FENCENO_SHIFT (0)
|
||||||
#define FBC_COMMAND 0x0320c
|
#define FBC_COMMAND 0x0320c
|
||||||
#define FBC_CMD_COMPRESS (1<<0)
|
#define FBC_CMD_COMPRESS (1<<0)
|
||||||
#define FBC_STATUS 0x03210
|
#define FBC_STATUS 0x03210
|
||||||
#define FBC_STAT_COMPRESSING (1<<31)
|
#define FBC_STAT_COMPRESSING (1<<31)
|
||||||
#define FBC_STAT_COMPRESSED (1<<30)
|
#define FBC_STAT_COMPRESSED (1<<30)
|
||||||
#define FBC_STAT_MODIFIED (1<<29)
|
#define FBC_STAT_MODIFIED (1<<29)
|
||||||
#define FBC_STAT_CURRENT_LINE (1<<0)
|
#define FBC_STAT_CURRENT_LINE_SHIFT (0)
|
||||||
#define FBC_CONTROL2 0x03214
|
#define FBC_CONTROL2 0x03214
|
||||||
#define FBC_CTL_FENCE_DBL (0<<4)
|
#define FBC_CTL_FENCE_DBL (0<<4)
|
||||||
#define FBC_CTL_IDLE_IMM (0<<2)
|
#define FBC_CTL_IDLE_IMM (0<<2)
|
||||||
@@ -4165,6 +4168,10 @@
|
|||||||
#define GEN7_L3SQCREG4 0xb034
|
#define GEN7_L3SQCREG4 0xb034
|
||||||
#define L3SQ_URB_READ_CAM_MATCH_DISABLE (1<<27)
|
#define L3SQ_URB_READ_CAM_MATCH_DISABLE (1<<27)
|
||||||
|
|
||||||
|
/* GEN8 chicken */
|
||||||
|
#define HDC_CHICKEN0 0x7300
|
||||||
|
#define HDC_FORCE_NON_COHERENT (1<<4)
|
||||||
|
|
||||||
/* WaCatErrorRejectionIssue */
|
/* WaCatErrorRejectionIssue */
|
||||||
#define GEN7_SQ_CHICKEN_MBCUNIT_CONFIG 0x9030
|
#define GEN7_SQ_CHICKEN_MBCUNIT_CONFIG 0x9030
|
||||||
#define GEN7_SQ_CHICKEN_MBCUNIT_SQINTMOB (1<<11)
|
#define GEN7_SQ_CHICKEN_MBCUNIT_SQINTMOB (1<<11)
|
||||||
|
@@ -40,10 +40,13 @@ static u32 calc_residency(struct drm_device *dev, const u32 reg)
|
|||||||
struct drm_i915_private *dev_priv = dev->dev_private;
|
struct drm_i915_private *dev_priv = dev->dev_private;
|
||||||
u64 raw_time; /* 32b value may overflow during fixed point math */
|
u64 raw_time; /* 32b value may overflow during fixed point math */
|
||||||
u64 units = 128ULL, div = 100000ULL, bias = 100ULL;
|
u64 units = 128ULL, div = 100000ULL, bias = 100ULL;
|
||||||
|
u32 ret;
|
||||||
|
|
||||||
if (!intel_enable_rc6(dev))
|
if (!intel_enable_rc6(dev))
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
|
intel_runtime_pm_get(dev_priv);
|
||||||
|
|
||||||
/* On VLV, residency time is in CZ units rather than 1.28us */
|
/* On VLV, residency time is in CZ units rather than 1.28us */
|
||||||
if (IS_VALLEYVIEW(dev)) {
|
if (IS_VALLEYVIEW(dev)) {
|
||||||
u32 clkctl2;
|
u32 clkctl2;
|
||||||
@@ -52,7 +55,8 @@ static u32 calc_residency(struct drm_device *dev, const u32 reg)
|
|||||||
CLK_CTL2_CZCOUNT_30NS_SHIFT;
|
CLK_CTL2_CZCOUNT_30NS_SHIFT;
|
||||||
if (!clkctl2) {
|
if (!clkctl2) {
|
||||||
WARN(!clkctl2, "bogus CZ count value");
|
WARN(!clkctl2, "bogus CZ count value");
|
||||||
return 0;
|
ret = 0;
|
||||||
|
goto out;
|
||||||
}
|
}
|
||||||
units = DIV_ROUND_UP_ULL(30ULL * bias, (u64)clkctl2);
|
units = DIV_ROUND_UP_ULL(30ULL * bias, (u64)clkctl2);
|
||||||
if (I915_READ(VLV_COUNTER_CONTROL) & VLV_COUNT_RANGE_HIGH)
|
if (I915_READ(VLV_COUNTER_CONTROL) & VLV_COUNT_RANGE_HIGH)
|
||||||
@@ -62,7 +66,11 @@ static u32 calc_residency(struct drm_device *dev, const u32 reg)
|
|||||||
}
|
}
|
||||||
|
|
||||||
raw_time = I915_READ(reg) * units;
|
raw_time = I915_READ(reg) * units;
|
||||||
return DIV_ROUND_UP_ULL(raw_time, div);
|
ret = DIV_ROUND_UP_ULL(raw_time, div);
|
||||||
|
|
||||||
|
out:
|
||||||
|
intel_runtime_pm_put(dev_priv);
|
||||||
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
static ssize_t
|
static ssize_t
|
||||||
@@ -448,7 +456,9 @@ static ssize_t gt_rp_mhz_show(struct device *kdev, struct device_attribute *attr
|
|||||||
ret = mutex_lock_interruptible(&dev->struct_mutex);
|
ret = mutex_lock_interruptible(&dev->struct_mutex);
|
||||||
if (ret)
|
if (ret)
|
||||||
return ret;
|
return ret;
|
||||||
|
intel_runtime_pm_get(dev_priv);
|
||||||
rp_state_cap = I915_READ(GEN6_RP_STATE_CAP);
|
rp_state_cap = I915_READ(GEN6_RP_STATE_CAP);
|
||||||
|
intel_runtime_pm_put(dev_priv);
|
||||||
mutex_unlock(&dev->struct_mutex);
|
mutex_unlock(&dev->struct_mutex);
|
||||||
|
|
||||||
if (attr == &dev_attr_gt_RP0_freq_mhz) {
|
if (attr == &dev_attr_gt_RP0_freq_mhz) {
|
||||||
|
@@ -327,12 +327,12 @@ static int intel_bios_ssc_frequency(struct drm_device *dev,
|
|||||||
{
|
{
|
||||||
switch (INTEL_INFO(dev)->gen) {
|
switch (INTEL_INFO(dev)->gen) {
|
||||||
case 2:
|
case 2:
|
||||||
return alternate ? 66 : 48;
|
return alternate ? 66667 : 48000;
|
||||||
case 3:
|
case 3:
|
||||||
case 4:
|
case 4:
|
||||||
return alternate ? 100 : 96;
|
return alternate ? 100000 : 96000;
|
||||||
default:
|
default:
|
||||||
return alternate ? 100 : 120;
|
return alternate ? 100000 : 120000;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -796,7 +796,7 @@ init_vbt_defaults(struct drm_i915_private *dev_priv)
|
|||||||
*/
|
*/
|
||||||
dev_priv->vbt.lvds_ssc_freq = intel_bios_ssc_frequency(dev,
|
dev_priv->vbt.lvds_ssc_freq = intel_bios_ssc_frequency(dev,
|
||||||
!HAS_PCH_SPLIT(dev));
|
!HAS_PCH_SPLIT(dev));
|
||||||
DRM_DEBUG_KMS("Set default to SSC at %dMHz\n", dev_priv->vbt.lvds_ssc_freq);
|
DRM_DEBUG_KMS("Set default to SSC at %d kHz\n", dev_priv->vbt.lvds_ssc_freq);
|
||||||
|
|
||||||
for (port = PORT_A; port < I915_MAX_PORTS; port++) {
|
for (port = PORT_A; port < I915_MAX_PORTS; port++) {
|
||||||
struct ddi_vbt_port_info *info =
|
struct ddi_vbt_port_info *info =
|
||||||
|
@@ -39,7 +39,7 @@ struct vbt_header {
|
|||||||
u8 reserved0;
|
u8 reserved0;
|
||||||
u32 bdb_offset; /**< from beginning of VBT */
|
u32 bdb_offset; /**< from beginning of VBT */
|
||||||
u32 aim_offset[4]; /**< from beginning of VBT */
|
u32 aim_offset[4]; /**< from beginning of VBT */
|
||||||
} __attribute__((packed));
|
} __packed;
|
||||||
|
|
||||||
struct bdb_header {
|
struct bdb_header {
|
||||||
u8 signature[16]; /**< Always 'BIOS_DATA_BLOCK' */
|
u8 signature[16]; /**< Always 'BIOS_DATA_BLOCK' */
|
||||||
@@ -65,7 +65,7 @@ struct vbios_data {
|
|||||||
u8 rsvd4; /* popup memory size */
|
u8 rsvd4; /* popup memory size */
|
||||||
u8 resize_pci_bios;
|
u8 resize_pci_bios;
|
||||||
u8 rsvd5; /* is crt already on ddc2 */
|
u8 rsvd5; /* is crt already on ddc2 */
|
||||||
} __attribute__((packed));
|
} __packed;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* There are several types of BIOS data blocks (BDBs), each block has
|
* There are several types of BIOS data blocks (BDBs), each block has
|
||||||
@@ -142,7 +142,7 @@ struct bdb_general_features {
|
|||||||
u8 dp_ssc_enb:1; /* PCH attached eDP supports SSC */
|
u8 dp_ssc_enb:1; /* PCH attached eDP supports SSC */
|
||||||
u8 dp_ssc_freq:1; /* SSC freq for PCH attached eDP */
|
u8 dp_ssc_freq:1; /* SSC freq for PCH attached eDP */
|
||||||
u8 rsvd11:3; /* finish byte */
|
u8 rsvd11:3; /* finish byte */
|
||||||
} __attribute__((packed));
|
} __packed;
|
||||||
|
|
||||||
/* pre-915 */
|
/* pre-915 */
|
||||||
#define GPIO_PIN_DVI_LVDS 0x03 /* "DVI/LVDS DDC GPIO pins" */
|
#define GPIO_PIN_DVI_LVDS 0x03 /* "DVI/LVDS DDC GPIO pins" */
|
||||||
@@ -225,7 +225,7 @@ struct old_child_dev_config {
|
|||||||
u8 dvo2_wiring;
|
u8 dvo2_wiring;
|
||||||
u16 extended_type;
|
u16 extended_type;
|
||||||
u8 dvo_function;
|
u8 dvo_function;
|
||||||
} __attribute__((packed));
|
} __packed;
|
||||||
|
|
||||||
/* This one contains field offsets that are known to be common for all BDB
|
/* This one contains field offsets that are known to be common for all BDB
|
||||||
* versions. Notice that the meaning of the contents contents may still change,
|
* versions. Notice that the meaning of the contents contents may still change,
|
||||||
@@ -238,7 +238,7 @@ struct common_child_dev_config {
|
|||||||
u8 not_common2[2];
|
u8 not_common2[2];
|
||||||
u8 ddc_pin;
|
u8 ddc_pin;
|
||||||
u16 edid_ptr;
|
u16 edid_ptr;
|
||||||
} __attribute__((packed));
|
} __packed;
|
||||||
|
|
||||||
/* This field changes depending on the BDB version, so the most reliable way to
|
/* This field changes depending on the BDB version, so the most reliable way to
|
||||||
* read it is by checking the BDB version and reading the raw pointer. */
|
* read it is by checking the BDB version and reading the raw pointer. */
|
||||||
@@ -279,7 +279,7 @@ struct bdb_general_definitions {
|
|||||||
* sizeof(child_device_config);
|
* sizeof(child_device_config);
|
||||||
*/
|
*/
|
||||||
union child_device_config devices[0];
|
union child_device_config devices[0];
|
||||||
} __attribute__((packed));
|
} __packed;
|
||||||
|
|
||||||
struct bdb_lvds_options {
|
struct bdb_lvds_options {
|
||||||
u8 panel_type;
|
u8 panel_type;
|
||||||
@@ -293,7 +293,7 @@ struct bdb_lvds_options {
|
|||||||
u8 lvds_edid:1;
|
u8 lvds_edid:1;
|
||||||
u8 rsvd2:1;
|
u8 rsvd2:1;
|
||||||
u8 rsvd4;
|
u8 rsvd4;
|
||||||
} __attribute__((packed));
|
} __packed;
|
||||||
|
|
||||||
/* LFP pointer table contains entries to the struct below */
|
/* LFP pointer table contains entries to the struct below */
|
||||||
struct bdb_lvds_lfp_data_ptr {
|
struct bdb_lvds_lfp_data_ptr {
|
||||||
@@ -303,12 +303,12 @@ struct bdb_lvds_lfp_data_ptr {
|
|||||||
u8 dvo_table_size;
|
u8 dvo_table_size;
|
||||||
u16 panel_pnp_id_offset;
|
u16 panel_pnp_id_offset;
|
||||||
u8 pnp_table_size;
|
u8 pnp_table_size;
|
||||||
} __attribute__((packed));
|
} __packed;
|
||||||
|
|
||||||
struct bdb_lvds_lfp_data_ptrs {
|
struct bdb_lvds_lfp_data_ptrs {
|
||||||
u8 lvds_entries; /* followed by one or more lvds_data_ptr structs */
|
u8 lvds_entries; /* followed by one or more lvds_data_ptr structs */
|
||||||
struct bdb_lvds_lfp_data_ptr ptr[16];
|
struct bdb_lvds_lfp_data_ptr ptr[16];
|
||||||
} __attribute__((packed));
|
} __packed;
|
||||||
|
|
||||||
/* LFP data has 3 blocks per entry */
|
/* LFP data has 3 blocks per entry */
|
||||||
struct lvds_fp_timing {
|
struct lvds_fp_timing {
|
||||||
@@ -325,7 +325,7 @@ struct lvds_fp_timing {
|
|||||||
u32 pfit_reg;
|
u32 pfit_reg;
|
||||||
u32 pfit_reg_val;
|
u32 pfit_reg_val;
|
||||||
u16 terminator;
|
u16 terminator;
|
||||||
} __attribute__((packed));
|
} __packed;
|
||||||
|
|
||||||
struct lvds_dvo_timing {
|
struct lvds_dvo_timing {
|
||||||
u16 clock; /**< In 10khz */
|
u16 clock; /**< In 10khz */
|
||||||
@@ -353,7 +353,7 @@ struct lvds_dvo_timing {
|
|||||||
u8 vsync_positive:1;
|
u8 vsync_positive:1;
|
||||||
u8 hsync_positive:1;
|
u8 hsync_positive:1;
|
||||||
u8 rsvd2:1;
|
u8 rsvd2:1;
|
||||||
} __attribute__((packed));
|
} __packed;
|
||||||
|
|
||||||
struct lvds_pnp_id {
|
struct lvds_pnp_id {
|
||||||
u16 mfg_name;
|
u16 mfg_name;
|
||||||
@@ -361,17 +361,17 @@ struct lvds_pnp_id {
|
|||||||
u32 serial;
|
u32 serial;
|
||||||
u8 mfg_week;
|
u8 mfg_week;
|
||||||
u8 mfg_year;
|
u8 mfg_year;
|
||||||
} __attribute__((packed));
|
} __packed;
|
||||||
|
|
||||||
struct bdb_lvds_lfp_data_entry {
|
struct bdb_lvds_lfp_data_entry {
|
||||||
struct lvds_fp_timing fp_timing;
|
struct lvds_fp_timing fp_timing;
|
||||||
struct lvds_dvo_timing dvo_timing;
|
struct lvds_dvo_timing dvo_timing;
|
||||||
struct lvds_pnp_id pnp_id;
|
struct lvds_pnp_id pnp_id;
|
||||||
} __attribute__((packed));
|
} __packed;
|
||||||
|
|
||||||
struct bdb_lvds_lfp_data {
|
struct bdb_lvds_lfp_data {
|
||||||
struct bdb_lvds_lfp_data_entry data[16];
|
struct bdb_lvds_lfp_data_entry data[16];
|
||||||
} __attribute__((packed));
|
} __packed;
|
||||||
|
|
||||||
struct aimdb_header {
|
struct aimdb_header {
|
||||||
char signature[16];
|
char signature[16];
|
||||||
@@ -379,12 +379,12 @@ struct aimdb_header {
|
|||||||
u16 aimdb_version;
|
u16 aimdb_version;
|
||||||
u16 aimdb_header_size;
|
u16 aimdb_header_size;
|
||||||
u16 aimdb_size;
|
u16 aimdb_size;
|
||||||
} __attribute__((packed));
|
} __packed;
|
||||||
|
|
||||||
struct aimdb_block {
|
struct aimdb_block {
|
||||||
u8 aimdb_id;
|
u8 aimdb_id;
|
||||||
u16 aimdb_size;
|
u16 aimdb_size;
|
||||||
} __attribute__((packed));
|
} __packed;
|
||||||
|
|
||||||
struct vch_panel_data {
|
struct vch_panel_data {
|
||||||
u16 fp_timing_offset;
|
u16 fp_timing_offset;
|
||||||
@@ -395,12 +395,12 @@ struct vch_panel_data {
|
|||||||
u8 text_fitting_size;
|
u8 text_fitting_size;
|
||||||
u16 graphics_fitting_offset;
|
u16 graphics_fitting_offset;
|
||||||
u8 graphics_fitting_size;
|
u8 graphics_fitting_size;
|
||||||
} __attribute__((packed));
|
} __packed;
|
||||||
|
|
||||||
struct vch_bdb_22 {
|
struct vch_bdb_22 {
|
||||||
struct aimdb_block aimdb_block;
|
struct aimdb_block aimdb_block;
|
||||||
struct vch_panel_data panels[16];
|
struct vch_panel_data panels[16];
|
||||||
} __attribute__((packed));
|
} __packed;
|
||||||
|
|
||||||
struct bdb_sdvo_lvds_options {
|
struct bdb_sdvo_lvds_options {
|
||||||
u8 panel_backlight;
|
u8 panel_backlight;
|
||||||
@@ -416,7 +416,7 @@ struct bdb_sdvo_lvds_options {
|
|||||||
u8 panel_misc_bits_2;
|
u8 panel_misc_bits_2;
|
||||||
u8 panel_misc_bits_3;
|
u8 panel_misc_bits_3;
|
||||||
u8 panel_misc_bits_4;
|
u8 panel_misc_bits_4;
|
||||||
} __attribute__((packed));
|
} __packed;
|
||||||
|
|
||||||
|
|
||||||
#define BDB_DRIVER_FEATURE_NO_LVDS 0
|
#define BDB_DRIVER_FEATURE_NO_LVDS 0
|
||||||
@@ -462,7 +462,7 @@ struct bdb_driver_features {
|
|||||||
|
|
||||||
u8 hdmi_termination;
|
u8 hdmi_termination;
|
||||||
u8 custom_vbt_version;
|
u8 custom_vbt_version;
|
||||||
} __attribute__((packed));
|
} __packed;
|
||||||
|
|
||||||
#define EDP_18BPP 0
|
#define EDP_18BPP 0
|
||||||
#define EDP_24BPP 1
|
#define EDP_24BPP 1
|
||||||
@@ -487,14 +487,14 @@ struct edp_power_seq {
|
|||||||
u16 t9;
|
u16 t9;
|
||||||
u16 t10;
|
u16 t10;
|
||||||
u16 t11_t12;
|
u16 t11_t12;
|
||||||
} __attribute__ ((packed));
|
} __packed;
|
||||||
|
|
||||||
struct edp_link_params {
|
struct edp_link_params {
|
||||||
u8 rate:4;
|
u8 rate:4;
|
||||||
u8 lanes:4;
|
u8 lanes:4;
|
||||||
u8 preemphasis:4;
|
u8 preemphasis:4;
|
||||||
u8 vswing:4;
|
u8 vswing:4;
|
||||||
} __attribute__ ((packed));
|
} __packed;
|
||||||
|
|
||||||
struct bdb_edp {
|
struct bdb_edp {
|
||||||
struct edp_power_seq power_seqs[16];
|
struct edp_power_seq power_seqs[16];
|
||||||
@@ -505,7 +505,7 @@ struct bdb_edp {
|
|||||||
/* ith bit indicates enabled/disabled for (i+1)th panel */
|
/* ith bit indicates enabled/disabled for (i+1)th panel */
|
||||||
u16 edp_s3d_feature;
|
u16 edp_s3d_feature;
|
||||||
u16 edp_t3_optimization;
|
u16 edp_t3_optimization;
|
||||||
} __attribute__ ((packed));
|
} __packed;
|
||||||
|
|
||||||
void intel_setup_bios(struct drm_device *dev);
|
void intel_setup_bios(struct drm_device *dev);
|
||||||
int intel_parse_bios(struct drm_device *dev);
|
int intel_parse_bios(struct drm_device *dev);
|
||||||
@@ -733,6 +733,6 @@ struct bdb_mipi {
|
|||||||
u32 hl_switch_cnt;
|
u32 hl_switch_cnt;
|
||||||
u32 lp_byte_clk;
|
u32 lp_byte_clk;
|
||||||
u32 clk_lane_switch_cnt;
|
u32 clk_lane_switch_cnt;
|
||||||
} __attribute__((packed));
|
} __packed;
|
||||||
|
|
||||||
#endif /* _I830_BIOS_H_ */
|
#endif /* _I830_BIOS_H_ */
|
||||||
|
@@ -73,7 +73,7 @@ static const u32 hsw_ddi_translations_hdmi[] = {
|
|||||||
};
|
};
|
||||||
|
|
||||||
static const u32 bdw_ddi_translations_edp[] = {
|
static const u32 bdw_ddi_translations_edp[] = {
|
||||||
0x00FFFFFF, 0x00000012, /* DP parameters */
|
0x00FFFFFF, 0x00000012, /* eDP parameters */
|
||||||
0x00EBAFFF, 0x00020011,
|
0x00EBAFFF, 0x00020011,
|
||||||
0x00C71FFF, 0x0006000F,
|
0x00C71FFF, 0x0006000F,
|
||||||
0x00FFFFFF, 0x00020011,
|
0x00FFFFFF, 0x00020011,
|
||||||
@@ -696,21 +696,23 @@ intel_ddi_calculate_wrpll(int clock /* in Hz */,
|
|||||||
*n2_out = best.n2;
|
*n2_out = best.n2;
|
||||||
*p_out = best.p;
|
*p_out = best.p;
|
||||||
*r2_out = best.r2;
|
*r2_out = best.r2;
|
||||||
|
|
||||||
DRM_DEBUG_KMS("WRPLL: %dHz refresh rate with p=%d, n2=%d r2=%d\n",
|
|
||||||
clock, *p_out, *n2_out, *r2_out);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool intel_ddi_pll_mode_set(struct drm_crtc *crtc)
|
/*
|
||||||
|
* Tries to find a PLL for the CRTC. If it finds, it increases the refcount and
|
||||||
|
* stores it in intel_crtc->ddi_pll_sel, so other mode sets won't be able to
|
||||||
|
* steal the selected PLL. You need to call intel_ddi_pll_enable to actually
|
||||||
|
* enable the PLL.
|
||||||
|
*/
|
||||||
|
bool intel_ddi_pll_select(struct intel_crtc *intel_crtc)
|
||||||
{
|
{
|
||||||
struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
|
struct drm_crtc *crtc = &intel_crtc->base;
|
||||||
struct intel_encoder *intel_encoder = intel_ddi_get_crtc_encoder(crtc);
|
struct intel_encoder *intel_encoder = intel_ddi_get_crtc_encoder(crtc);
|
||||||
struct drm_encoder *encoder = &intel_encoder->base;
|
struct drm_encoder *encoder = &intel_encoder->base;
|
||||||
struct drm_i915_private *dev_priv = crtc->dev->dev_private;
|
struct drm_i915_private *dev_priv = crtc->dev->dev_private;
|
||||||
struct intel_ddi_plls *plls = &dev_priv->ddi_plls;
|
struct intel_ddi_plls *plls = &dev_priv->ddi_plls;
|
||||||
int type = intel_encoder->type;
|
int type = intel_encoder->type;
|
||||||
enum pipe pipe = intel_crtc->pipe;
|
enum pipe pipe = intel_crtc->pipe;
|
||||||
uint32_t reg, val;
|
|
||||||
int clock = intel_crtc->config.port_clock;
|
int clock = intel_crtc->config.port_clock;
|
||||||
|
|
||||||
intel_ddi_put_crtc_pll(crtc);
|
intel_ddi_put_crtc_pll(crtc);
|
||||||
@@ -734,10 +736,8 @@ bool intel_ddi_pll_mode_set(struct drm_crtc *crtc)
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* We don't need to turn any PLL on because we'll use LCPLL. */
|
|
||||||
return true;
|
|
||||||
|
|
||||||
} else if (type == INTEL_OUTPUT_HDMI) {
|
} else if (type == INTEL_OUTPUT_HDMI) {
|
||||||
|
uint32_t reg, val;
|
||||||
unsigned p, n2, r2;
|
unsigned p, n2, r2;
|
||||||
|
|
||||||
intel_ddi_calculate_wrpll(clock * 1000, &r2, &n2, &p);
|
intel_ddi_calculate_wrpll(clock * 1000, &r2, &n2, &p);
|
||||||
@@ -767,6 +767,9 @@ bool intel_ddi_pll_mode_set(struct drm_crtc *crtc)
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
DRM_DEBUG_KMS("WRPLL: %dKHz refresh rate with p=%d, n2=%d r2=%d\n",
|
||||||
|
clock, p, n2, r2);
|
||||||
|
|
||||||
if (reg == WRPLL_CTL1) {
|
if (reg == WRPLL_CTL1) {
|
||||||
plls->wrpll1_refcount++;
|
plls->wrpll1_refcount++;
|
||||||
intel_crtc->ddi_pll_sel = PORT_CLK_SEL_WRPLL1;
|
intel_crtc->ddi_pll_sel = PORT_CLK_SEL_WRPLL1;
|
||||||
@@ -780,29 +783,98 @@ bool intel_ddi_pll_mode_set(struct drm_crtc *crtc)
|
|||||||
DRM_DEBUG_KMS("Using SPLL on pipe %c\n",
|
DRM_DEBUG_KMS("Using SPLL on pipe %c\n",
|
||||||
pipe_name(pipe));
|
pipe_name(pipe));
|
||||||
plls->spll_refcount++;
|
plls->spll_refcount++;
|
||||||
reg = SPLL_CTL;
|
|
||||||
intel_crtc->ddi_pll_sel = PORT_CLK_SEL_SPLL;
|
intel_crtc->ddi_pll_sel = PORT_CLK_SEL_SPLL;
|
||||||
} else {
|
} else {
|
||||||
DRM_ERROR("SPLL already in use\n");
|
DRM_ERROR("SPLL already in use\n");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
WARN(I915_READ(reg) & SPLL_PLL_ENABLE,
|
|
||||||
"SPLL already enabled\n");
|
|
||||||
|
|
||||||
val = SPLL_PLL_ENABLE | SPLL_PLL_FREQ_1350MHz | SPLL_PLL_SSC;
|
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
WARN(1, "Invalid DDI encoder type %d\n", type);
|
WARN(1, "Invalid DDI encoder type %d\n", type);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
I915_WRITE(reg, val);
|
|
||||||
udelay(20);
|
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* To be called after intel_ddi_pll_select(). That one selects the PLL to be
|
||||||
|
* used, this one actually enables the PLL.
|
||||||
|
*/
|
||||||
|
void intel_ddi_pll_enable(struct intel_crtc *crtc)
|
||||||
|
{
|
||||||
|
struct drm_device *dev = crtc->base.dev;
|
||||||
|
struct drm_i915_private *dev_priv = dev->dev_private;
|
||||||
|
struct intel_ddi_plls *plls = &dev_priv->ddi_plls;
|
||||||
|
int clock = crtc->config.port_clock;
|
||||||
|
uint32_t reg, cur_val, new_val;
|
||||||
|
int refcount;
|
||||||
|
const char *pll_name;
|
||||||
|
uint32_t enable_bit = (1 << 31);
|
||||||
|
unsigned int p, n2, r2;
|
||||||
|
|
||||||
|
BUILD_BUG_ON(enable_bit != SPLL_PLL_ENABLE);
|
||||||
|
BUILD_BUG_ON(enable_bit != WRPLL_PLL_ENABLE);
|
||||||
|
|
||||||
|
switch (crtc->ddi_pll_sel) {
|
||||||
|
case PORT_CLK_SEL_LCPLL_2700:
|
||||||
|
case PORT_CLK_SEL_LCPLL_1350:
|
||||||
|
case PORT_CLK_SEL_LCPLL_810:
|
||||||
|
/*
|
||||||
|
* LCPLL should always be enabled at this point of the mode set
|
||||||
|
* sequence, so nothing to do.
|
||||||
|
*/
|
||||||
|
return;
|
||||||
|
|
||||||
|
case PORT_CLK_SEL_SPLL:
|
||||||
|
pll_name = "SPLL";
|
||||||
|
reg = SPLL_CTL;
|
||||||
|
refcount = plls->spll_refcount;
|
||||||
|
new_val = SPLL_PLL_ENABLE | SPLL_PLL_FREQ_1350MHz |
|
||||||
|
SPLL_PLL_SSC;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case PORT_CLK_SEL_WRPLL1:
|
||||||
|
case PORT_CLK_SEL_WRPLL2:
|
||||||
|
if (crtc->ddi_pll_sel == PORT_CLK_SEL_WRPLL1) {
|
||||||
|
pll_name = "WRPLL1";
|
||||||
|
reg = WRPLL_CTL1;
|
||||||
|
refcount = plls->wrpll1_refcount;
|
||||||
|
} else {
|
||||||
|
pll_name = "WRPLL2";
|
||||||
|
reg = WRPLL_CTL2;
|
||||||
|
refcount = plls->wrpll2_refcount;
|
||||||
|
}
|
||||||
|
|
||||||
|
intel_ddi_calculate_wrpll(clock * 1000, &r2, &n2, &p);
|
||||||
|
|
||||||
|
new_val = WRPLL_PLL_ENABLE | WRPLL_PLL_SELECT_LCPLL_2700 |
|
||||||
|
WRPLL_DIVIDER_REFERENCE(r2) |
|
||||||
|
WRPLL_DIVIDER_FEEDBACK(n2) | WRPLL_DIVIDER_POST(p);
|
||||||
|
|
||||||
|
break;
|
||||||
|
|
||||||
|
case PORT_CLK_SEL_NONE:
|
||||||
|
WARN(1, "Bad selected pll: PORT_CLK_SEL_NONE\n");
|
||||||
|
return;
|
||||||
|
default:
|
||||||
|
WARN(1, "Bad selected pll: 0x%08x\n", crtc->ddi_pll_sel);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
cur_val = I915_READ(reg);
|
||||||
|
|
||||||
|
WARN(refcount < 1, "Bad %s refcount: %d\n", pll_name, refcount);
|
||||||
|
if (refcount == 1) {
|
||||||
|
WARN(cur_val & enable_bit, "%s already enabled\n", pll_name);
|
||||||
|
I915_WRITE(reg, new_val);
|
||||||
|
POSTING_READ(reg);
|
||||||
|
udelay(20);
|
||||||
|
} else {
|
||||||
|
WARN((cur_val & enable_bit) == 0, "%s disabled\n", pll_name);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void intel_ddi_set_pipe_settings(struct drm_crtc *crtc)
|
void intel_ddi_set_pipe_settings(struct drm_crtc *crtc)
|
||||||
{
|
{
|
||||||
struct drm_i915_private *dev_priv = crtc->dev->dev_private;
|
struct drm_i915_private *dev_priv = crtc->dev->dev_private;
|
||||||
@@ -1122,9 +1194,7 @@ static void intel_ddi_pre_enable(struct intel_encoder *intel_encoder)
|
|||||||
|
|
||||||
if (type == INTEL_OUTPUT_EDP) {
|
if (type == INTEL_OUTPUT_EDP) {
|
||||||
struct intel_dp *intel_dp = enc_to_intel_dp(encoder);
|
struct intel_dp *intel_dp = enc_to_intel_dp(encoder);
|
||||||
ironlake_edp_panel_vdd_on(intel_dp);
|
|
||||||
ironlake_edp_panel_on(intel_dp);
|
ironlake_edp_panel_on(intel_dp);
|
||||||
ironlake_edp_panel_vdd_off(intel_dp, true);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
WARN_ON(intel_crtc->ddi_pll_sel == PORT_CLK_SEL_NONE);
|
WARN_ON(intel_crtc->ddi_pll_sel == PORT_CLK_SEL_NONE);
|
||||||
@@ -1167,7 +1237,6 @@ static void intel_ddi_post_disable(struct intel_encoder *intel_encoder)
|
|||||||
|
|
||||||
if (type == INTEL_OUTPUT_DISPLAYPORT || type == INTEL_OUTPUT_EDP) {
|
if (type == INTEL_OUTPUT_DISPLAYPORT || type == INTEL_OUTPUT_EDP) {
|
||||||
struct intel_dp *intel_dp = enc_to_intel_dp(encoder);
|
struct intel_dp *intel_dp = enc_to_intel_dp(encoder);
|
||||||
ironlake_edp_panel_vdd_on(intel_dp);
|
|
||||||
intel_dp_sink_dpms(intel_dp, DRM_MODE_DPMS_OFF);
|
intel_dp_sink_dpms(intel_dp, DRM_MODE_DPMS_OFF);
|
||||||
ironlake_edp_panel_off(intel_dp);
|
ironlake_edp_panel_off(intel_dp);
|
||||||
}
|
}
|
||||||
|
@@ -90,8 +90,8 @@ intel_fdi_link_freq(struct drm_device *dev)
|
|||||||
|
|
||||||
static const intel_limit_t intel_limits_i8xx_dac = {
|
static const intel_limit_t intel_limits_i8xx_dac = {
|
||||||
.dot = { .min = 25000, .max = 350000 },
|
.dot = { .min = 25000, .max = 350000 },
|
||||||
.vco = { .min = 930000, .max = 1400000 },
|
.vco = { .min = 908000, .max = 1512000 },
|
||||||
.n = { .min = 3, .max = 16 },
|
.n = { .min = 2, .max = 16 },
|
||||||
.m = { .min = 96, .max = 140 },
|
.m = { .min = 96, .max = 140 },
|
||||||
.m1 = { .min = 18, .max = 26 },
|
.m1 = { .min = 18, .max = 26 },
|
||||||
.m2 = { .min = 6, .max = 16 },
|
.m2 = { .min = 6, .max = 16 },
|
||||||
@@ -103,8 +103,8 @@ static const intel_limit_t intel_limits_i8xx_dac = {
|
|||||||
|
|
||||||
static const intel_limit_t intel_limits_i8xx_dvo = {
|
static const intel_limit_t intel_limits_i8xx_dvo = {
|
||||||
.dot = { .min = 25000, .max = 350000 },
|
.dot = { .min = 25000, .max = 350000 },
|
||||||
.vco = { .min = 930000, .max = 1400000 },
|
.vco = { .min = 908000, .max = 1512000 },
|
||||||
.n = { .min = 3, .max = 16 },
|
.n = { .min = 2, .max = 16 },
|
||||||
.m = { .min = 96, .max = 140 },
|
.m = { .min = 96, .max = 140 },
|
||||||
.m1 = { .min = 18, .max = 26 },
|
.m1 = { .min = 18, .max = 26 },
|
||||||
.m2 = { .min = 6, .max = 16 },
|
.m2 = { .min = 6, .max = 16 },
|
||||||
@@ -116,8 +116,8 @@ static const intel_limit_t intel_limits_i8xx_dvo = {
|
|||||||
|
|
||||||
static const intel_limit_t intel_limits_i8xx_lvds = {
|
static const intel_limit_t intel_limits_i8xx_lvds = {
|
||||||
.dot = { .min = 25000, .max = 350000 },
|
.dot = { .min = 25000, .max = 350000 },
|
||||||
.vco = { .min = 930000, .max = 1400000 },
|
.vco = { .min = 908000, .max = 1512000 },
|
||||||
.n = { .min = 3, .max = 16 },
|
.n = { .min = 2, .max = 16 },
|
||||||
.m = { .min = 96, .max = 140 },
|
.m = { .min = 96, .max = 140 },
|
||||||
.m1 = { .min = 18, .max = 26 },
|
.m1 = { .min = 18, .max = 26 },
|
||||||
.m2 = { .min = 6, .max = 16 },
|
.m2 = { .min = 6, .max = 16 },
|
||||||
@@ -329,6 +329,8 @@ static void vlv_clock(int refclk, intel_clock_t *clock)
|
|||||||
{
|
{
|
||||||
clock->m = clock->m1 * clock->m2;
|
clock->m = clock->m1 * clock->m2;
|
||||||
clock->p = clock->p1 * clock->p2;
|
clock->p = clock->p1 * clock->p2;
|
||||||
|
if (WARN_ON(clock->n == 0 || clock->p == 0))
|
||||||
|
return;
|
||||||
clock->vco = DIV_ROUND_CLOSEST(refclk * clock->m, clock->n);
|
clock->vco = DIV_ROUND_CLOSEST(refclk * clock->m, clock->n);
|
||||||
clock->dot = DIV_ROUND_CLOSEST(clock->vco, clock->p);
|
clock->dot = DIV_ROUND_CLOSEST(clock->vco, clock->p);
|
||||||
}
|
}
|
||||||
@@ -430,6 +432,8 @@ static void pineview_clock(int refclk, intel_clock_t *clock)
|
|||||||
{
|
{
|
||||||
clock->m = clock->m2 + 2;
|
clock->m = clock->m2 + 2;
|
||||||
clock->p = clock->p1 * clock->p2;
|
clock->p = clock->p1 * clock->p2;
|
||||||
|
if (WARN_ON(clock->n == 0 || clock->p == 0))
|
||||||
|
return;
|
||||||
clock->vco = DIV_ROUND_CLOSEST(refclk * clock->m, clock->n);
|
clock->vco = DIV_ROUND_CLOSEST(refclk * clock->m, clock->n);
|
||||||
clock->dot = DIV_ROUND_CLOSEST(clock->vco, clock->p);
|
clock->dot = DIV_ROUND_CLOSEST(clock->vco, clock->p);
|
||||||
}
|
}
|
||||||
@@ -443,6 +447,8 @@ static void i9xx_clock(int refclk, intel_clock_t *clock)
|
|||||||
{
|
{
|
||||||
clock->m = i9xx_dpll_compute_m(clock);
|
clock->m = i9xx_dpll_compute_m(clock);
|
||||||
clock->p = clock->p1 * clock->p2;
|
clock->p = clock->p1 * clock->p2;
|
||||||
|
if (WARN_ON(clock->n + 2 == 0 || clock->p == 0))
|
||||||
|
return;
|
||||||
clock->vco = DIV_ROUND_CLOSEST(refclk * clock->m, clock->n + 2);
|
clock->vco = DIV_ROUND_CLOSEST(refclk * clock->m, clock->n + 2);
|
||||||
clock->dot = DIV_ROUND_CLOSEST(clock->vco, clock->p);
|
clock->dot = DIV_ROUND_CLOSEST(clock->vco, clock->p);
|
||||||
}
|
}
|
||||||
@@ -1361,6 +1367,10 @@ static void intel_init_dpio(struct drm_device *dev)
|
|||||||
if (!IS_VALLEYVIEW(dev))
|
if (!IS_VALLEYVIEW(dev))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
/* Enable the CRI clock source so we can get at the display */
|
||||||
|
I915_WRITE(DPLL(PIPE_B), I915_READ(DPLL(PIPE_B)) |
|
||||||
|
DPLL_INTEGRATED_CRI_CLK_VLV);
|
||||||
|
|
||||||
DPIO_PHY_IOSF_PORT(DPIO_PHY0) = IOSF_PORT_DPIO;
|
DPIO_PHY_IOSF_PORT(DPIO_PHY0) = IOSF_PORT_DPIO;
|
||||||
/*
|
/*
|
||||||
* From VLV2A0_DP_eDP_DPIO_driver_vbios_notes_10.docx -
|
* From VLV2A0_DP_eDP_DPIO_driver_vbios_notes_10.docx -
|
||||||
@@ -4751,9 +4761,8 @@ static int i9xx_get_refclk(struct drm_crtc *crtc, int num_connectors)
|
|||||||
refclk = 100000;
|
refclk = 100000;
|
||||||
} else if (intel_pipe_has_type(crtc, INTEL_OUTPUT_LVDS) &&
|
} else if (intel_pipe_has_type(crtc, INTEL_OUTPUT_LVDS) &&
|
||||||
intel_panel_use_ssc(dev_priv) && num_connectors < 2) {
|
intel_panel_use_ssc(dev_priv) && num_connectors < 2) {
|
||||||
refclk = dev_priv->vbt.lvds_ssc_freq * 1000;
|
refclk = dev_priv->vbt.lvds_ssc_freq;
|
||||||
DRM_DEBUG_KMS("using SSC reference clock of %d MHz\n",
|
DRM_DEBUG_KMS("using SSC reference clock of %d kHz\n", refclk);
|
||||||
refclk / 1000);
|
|
||||||
} else if (!IS_GEN2(dev)) {
|
} else if (!IS_GEN2(dev)) {
|
||||||
refclk = 96000;
|
refclk = 96000;
|
||||||
} else {
|
} else {
|
||||||
@@ -5899,9 +5908,9 @@ static int ironlake_get_refclk(struct drm_crtc *crtc)
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (is_lvds && intel_panel_use_ssc(dev_priv) && num_connectors < 2) {
|
if (is_lvds && intel_panel_use_ssc(dev_priv) && num_connectors < 2) {
|
||||||
DRM_DEBUG_KMS("using SSC reference clock of %d MHz\n",
|
DRM_DEBUG_KMS("using SSC reference clock of %d kHz\n",
|
||||||
dev_priv->vbt.lvds_ssc_freq);
|
dev_priv->vbt.lvds_ssc_freq);
|
||||||
return dev_priv->vbt.lvds_ssc_freq * 1000;
|
return dev_priv->vbt.lvds_ssc_freq;
|
||||||
}
|
}
|
||||||
|
|
||||||
return 120000;
|
return 120000;
|
||||||
@@ -6163,7 +6172,7 @@ static uint32_t ironlake_compute_dpll(struct intel_crtc *intel_crtc,
|
|||||||
factor = 21;
|
factor = 21;
|
||||||
if (is_lvds) {
|
if (is_lvds) {
|
||||||
if ((intel_panel_use_ssc(dev_priv) &&
|
if ((intel_panel_use_ssc(dev_priv) &&
|
||||||
dev_priv->vbt.lvds_ssc_freq == 100) ||
|
dev_priv->vbt.lvds_ssc_freq == 100000) ||
|
||||||
(HAS_PCH_IBX(dev) && intel_is_dual_link_lvds(dev)))
|
(HAS_PCH_IBX(dev) && intel_is_dual_link_lvds(dev)))
|
||||||
factor = 25;
|
factor = 25;
|
||||||
} else if (intel_crtc->config.sdvo_tv_clock)
|
} else if (intel_crtc->config.sdvo_tv_clock)
|
||||||
@@ -6484,7 +6493,7 @@ static void assert_can_disable_lcpll(struct drm_i915_private *dev_priv)
|
|||||||
uint32_t val;
|
uint32_t val;
|
||||||
|
|
||||||
list_for_each_entry(crtc, &dev->mode_config.crtc_list, base.head)
|
list_for_each_entry(crtc, &dev->mode_config.crtc_list, base.head)
|
||||||
WARN(crtc->base.enabled, "CRTC for pipe %c enabled\n",
|
WARN(crtc->active, "CRTC for pipe %c enabled\n",
|
||||||
pipe_name(crtc->pipe));
|
pipe_name(crtc->pipe));
|
||||||
|
|
||||||
WARN(I915_READ(HSW_PWR_WELL_DRIVER), "Power well on\n");
|
WARN(I915_READ(HSW_PWR_WELL_DRIVER), "Power well on\n");
|
||||||
@@ -6504,7 +6513,7 @@ static void assert_can_disable_lcpll(struct drm_i915_private *dev_priv)
|
|||||||
|
|
||||||
spin_lock_irqsave(&dev_priv->irq_lock, irqflags);
|
spin_lock_irqsave(&dev_priv->irq_lock, irqflags);
|
||||||
val = I915_READ(DEIMR);
|
val = I915_READ(DEIMR);
|
||||||
WARN((val & ~DE_PCH_EVENT_IVB) != val,
|
WARN((val | DE_PCH_EVENT_IVB) != 0xffffffff,
|
||||||
"Unexpected DEIMR bits enabled: 0x%x\n", val);
|
"Unexpected DEIMR bits enabled: 0x%x\n", val);
|
||||||
val = I915_READ(SDEIMR);
|
val = I915_READ(SDEIMR);
|
||||||
WARN((val | SDE_HOTPLUG_MASK_CPT) != 0xffffffff,
|
WARN((val | SDE_HOTPLUG_MASK_CPT) != 0xffffffff,
|
||||||
@@ -6628,6 +6637,8 @@ void hsw_enable_pc8_work(struct work_struct *__work)
|
|||||||
struct drm_device *dev = dev_priv->dev;
|
struct drm_device *dev = dev_priv->dev;
|
||||||
uint32_t val;
|
uint32_t val;
|
||||||
|
|
||||||
|
WARN_ON(!HAS_PC8(dev));
|
||||||
|
|
||||||
if (dev_priv->pc8.enabled)
|
if (dev_priv->pc8.enabled)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
@@ -6644,6 +6655,8 @@ void hsw_enable_pc8_work(struct work_struct *__work)
|
|||||||
lpt_disable_clkout_dp(dev);
|
lpt_disable_clkout_dp(dev);
|
||||||
hsw_pc8_disable_interrupts(dev);
|
hsw_pc8_disable_interrupts(dev);
|
||||||
hsw_disable_lcpll(dev_priv, true, true);
|
hsw_disable_lcpll(dev_priv, true, true);
|
||||||
|
|
||||||
|
intel_runtime_pm_put(dev_priv);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void __hsw_enable_package_c8(struct drm_i915_private *dev_priv)
|
static void __hsw_enable_package_c8(struct drm_i915_private *dev_priv)
|
||||||
@@ -6673,12 +6686,16 @@ static void __hsw_disable_package_c8(struct drm_i915_private *dev_priv)
|
|||||||
if (dev_priv->pc8.disable_count != 1)
|
if (dev_priv->pc8.disable_count != 1)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
WARN_ON(!HAS_PC8(dev));
|
||||||
|
|
||||||
cancel_delayed_work_sync(&dev_priv->pc8.enable_work);
|
cancel_delayed_work_sync(&dev_priv->pc8.enable_work);
|
||||||
if (!dev_priv->pc8.enabled)
|
if (!dev_priv->pc8.enabled)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
DRM_DEBUG_KMS("Disabling package C8+\n");
|
DRM_DEBUG_KMS("Disabling package C8+\n");
|
||||||
|
|
||||||
|
intel_runtime_pm_get(dev_priv);
|
||||||
|
|
||||||
hsw_restore_lcpll(dev_priv);
|
hsw_restore_lcpll(dev_priv);
|
||||||
hsw_pc8_restore_interrupts(dev);
|
hsw_pc8_restore_interrupts(dev);
|
||||||
lpt_init_pch_refclk(dev);
|
lpt_init_pch_refclk(dev);
|
||||||
@@ -6885,8 +6902,9 @@ static int haswell_crtc_mode_set(struct drm_crtc *crtc,
|
|||||||
int plane = intel_crtc->plane;
|
int plane = intel_crtc->plane;
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
if (!intel_ddi_pll_mode_set(crtc))
|
if (!intel_ddi_pll_select(intel_crtc))
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
|
intel_ddi_pll_enable(intel_crtc);
|
||||||
|
|
||||||
if (intel_crtc->config.has_dp_encoder)
|
if (intel_crtc->config.has_dp_encoder)
|
||||||
intel_dp_set_m_n(intel_crtc);
|
intel_dp_set_m_n(intel_crtc);
|
||||||
@@ -7870,7 +7888,7 @@ static int i9xx_pll_refclk(struct drm_device *dev,
|
|||||||
u32 dpll = pipe_config->dpll_hw_state.dpll;
|
u32 dpll = pipe_config->dpll_hw_state.dpll;
|
||||||
|
|
||||||
if ((dpll & PLL_REF_INPUT_MASK) == PLLB_REF_INPUT_SPREADSPECTRUMIN)
|
if ((dpll & PLL_REF_INPUT_MASK) == PLLB_REF_INPUT_SPREADSPECTRUMIN)
|
||||||
return dev_priv->vbt.lvds_ssc_freq * 1000;
|
return dev_priv->vbt.lvds_ssc_freq;
|
||||||
else if (HAS_PCH_SPLIT(dev))
|
else if (HAS_PCH_SPLIT(dev))
|
||||||
return 120000;
|
return 120000;
|
||||||
else if (!IS_GEN2(dev))
|
else if (!IS_GEN2(dev))
|
||||||
@@ -7933,12 +7951,17 @@ static void i9xx_crtc_clock_get(struct intel_crtc *crtc,
|
|||||||
else
|
else
|
||||||
i9xx_clock(refclk, &clock);
|
i9xx_clock(refclk, &clock);
|
||||||
} else {
|
} else {
|
||||||
bool is_lvds = (pipe == 1) && (I915_READ(LVDS) & LVDS_PORT_EN);
|
u32 lvds = I915_READ(LVDS);
|
||||||
|
bool is_lvds = (pipe == 1) && (lvds & LVDS_PORT_EN);
|
||||||
|
|
||||||
if (is_lvds) {
|
if (is_lvds) {
|
||||||
clock.p1 = ffs((dpll & DPLL_FPA01_P1_POST_DIV_MASK_I830_LVDS) >>
|
clock.p1 = ffs((dpll & DPLL_FPA01_P1_POST_DIV_MASK_I830_LVDS) >>
|
||||||
DPLL_FPA01_P1_POST_DIV_SHIFT);
|
DPLL_FPA01_P1_POST_DIV_SHIFT);
|
||||||
clock.p2 = 14;
|
|
||||||
|
if (lvds & LVDS_CLKB_POWER_UP)
|
||||||
|
clock.p2 = 7;
|
||||||
|
else
|
||||||
|
clock.p2 = 14;
|
||||||
} else {
|
} else {
|
||||||
if (dpll & PLL_P1_DIVIDE_BY_TWO)
|
if (dpll & PLL_P1_DIVIDE_BY_TWO)
|
||||||
clock.p1 = 2;
|
clock.p1 = 2;
|
||||||
@@ -10122,10 +10145,13 @@ static void intel_crtc_init(struct drm_device *dev, int pipe)
|
|||||||
intel_crtc->lut_b[i] = i;
|
intel_crtc->lut_b[i] = i;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Swap pipes & planes for FBC on pre-965 */
|
/*
|
||||||
|
* On gen2/3 only plane A can do fbc, but the panel fitter and lvds port
|
||||||
|
* is hooked to plane B. Hence we want plane A feeding pipe B.
|
||||||
|
*/
|
||||||
intel_crtc->pipe = pipe;
|
intel_crtc->pipe = pipe;
|
||||||
intel_crtc->plane = pipe;
|
intel_crtc->plane = pipe;
|
||||||
if (IS_MOBILE(dev) && IS_GEN3(dev)) {
|
if (IS_MOBILE(dev) && INTEL_INFO(dev)->gen < 4) {
|
||||||
DRM_DEBUG_KMS("swapping pipes & planes for FBC\n");
|
DRM_DEBUG_KMS("swapping pipes & planes for FBC\n");
|
||||||
intel_crtc->plane = !pipe;
|
intel_crtc->plane = !pipe;
|
||||||
}
|
}
|
||||||
@@ -10779,17 +10805,10 @@ static void i915_disable_vga(struct drm_device *dev)
|
|||||||
|
|
||||||
void intel_modeset_init_hw(struct drm_device *dev)
|
void intel_modeset_init_hw(struct drm_device *dev)
|
||||||
{
|
{
|
||||||
struct drm_i915_private *dev_priv = dev->dev_private;
|
|
||||||
|
|
||||||
intel_prepare_ddi(dev);
|
intel_prepare_ddi(dev);
|
||||||
|
|
||||||
intel_init_clock_gating(dev);
|
intel_init_clock_gating(dev);
|
||||||
|
|
||||||
/* Enable the CRI clock source so we can get at the display */
|
|
||||||
if (IS_VALLEYVIEW(dev))
|
|
||||||
I915_WRITE(DPLL(PIPE_B), I915_READ(DPLL(PIPE_B)) |
|
|
||||||
DPLL_INTEGRATED_CRI_CLK_VLV);
|
|
||||||
|
|
||||||
intel_init_dpio(dev);
|
intel_init_dpio(dev);
|
||||||
|
|
||||||
mutex_lock(&dev->struct_mutex);
|
mutex_lock(&dev->struct_mutex);
|
||||||
|
@@ -1038,6 +1038,8 @@ static void ironlake_wait_panel_status(struct intel_dp *intel_dp,
|
|||||||
I915_READ(pp_stat_reg),
|
I915_READ(pp_stat_reg),
|
||||||
I915_READ(pp_ctrl_reg));
|
I915_READ(pp_ctrl_reg));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
DRM_DEBUG_KMS("Wait complete\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
static void ironlake_wait_panel_on(struct intel_dp *intel_dp)
|
static void ironlake_wait_panel_on(struct intel_dp *intel_dp)
|
||||||
@@ -1093,6 +1095,8 @@ void ironlake_edp_panel_vdd_on(struct intel_dp *intel_dp)
|
|||||||
if (ironlake_edp_have_panel_vdd(intel_dp))
|
if (ironlake_edp_have_panel_vdd(intel_dp))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
intel_runtime_pm_get(dev_priv);
|
||||||
|
|
||||||
DRM_DEBUG_KMS("Turning eDP VDD on\n");
|
DRM_DEBUG_KMS("Turning eDP VDD on\n");
|
||||||
|
|
||||||
if (!ironlake_edp_have_panel_power(intel_dp))
|
if (!ironlake_edp_have_panel_power(intel_dp))
|
||||||
@@ -1141,7 +1145,11 @@ static void ironlake_panel_vdd_off_sync(struct intel_dp *intel_dp)
|
|||||||
/* Make sure sequencer is idle before allowing subsequent activity */
|
/* Make sure sequencer is idle before allowing subsequent activity */
|
||||||
DRM_DEBUG_KMS("PP_STATUS: 0x%08x PP_CONTROL: 0x%08x\n",
|
DRM_DEBUG_KMS("PP_STATUS: 0x%08x PP_CONTROL: 0x%08x\n",
|
||||||
I915_READ(pp_stat_reg), I915_READ(pp_ctrl_reg));
|
I915_READ(pp_stat_reg), I915_READ(pp_ctrl_reg));
|
||||||
msleep(intel_dp->panel_power_down_delay);
|
|
||||||
|
if ((pp & POWER_TARGET_ON) == 0)
|
||||||
|
msleep(intel_dp->panel_power_cycle_delay);
|
||||||
|
|
||||||
|
intel_runtime_pm_put(dev_priv);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1234,20 +1242,16 @@ void ironlake_edp_panel_off(struct intel_dp *intel_dp)
|
|||||||
|
|
||||||
DRM_DEBUG_KMS("Turn eDP power off\n");
|
DRM_DEBUG_KMS("Turn eDP power off\n");
|
||||||
|
|
||||||
WARN(!intel_dp->want_panel_vdd, "Need VDD to turn off panel\n");
|
|
||||||
|
|
||||||
pp = ironlake_get_pp_control(intel_dp);
|
pp = ironlake_get_pp_control(intel_dp);
|
||||||
/* We need to switch off panel power _and_ force vdd, for otherwise some
|
/* We need to switch off panel power _and_ force vdd, for otherwise some
|
||||||
* panels get very unhappy and cease to work. */
|
* panels get very unhappy and cease to work. */
|
||||||
pp &= ~(POWER_TARGET_ON | EDP_FORCE_VDD | PANEL_POWER_RESET | EDP_BLC_ENABLE);
|
pp &= ~(POWER_TARGET_ON | PANEL_POWER_RESET | EDP_BLC_ENABLE);
|
||||||
|
|
||||||
pp_ctrl_reg = _pp_ctrl_reg(intel_dp);
|
pp_ctrl_reg = _pp_ctrl_reg(intel_dp);
|
||||||
|
|
||||||
I915_WRITE(pp_ctrl_reg, pp);
|
I915_WRITE(pp_ctrl_reg, pp);
|
||||||
POSTING_READ(pp_ctrl_reg);
|
POSTING_READ(pp_ctrl_reg);
|
||||||
|
|
||||||
intel_dp->want_panel_vdd = false;
|
|
||||||
|
|
||||||
ironlake_wait_panel_off(intel_dp);
|
ironlake_wait_panel_off(intel_dp);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1773,7 +1777,6 @@ static void intel_disable_dp(struct intel_encoder *encoder)
|
|||||||
|
|
||||||
/* Make sure the panel is off before trying to change the mode. But also
|
/* Make sure the panel is off before trying to change the mode. But also
|
||||||
* ensure that we have vdd while we switch off the panel. */
|
* ensure that we have vdd while we switch off the panel. */
|
||||||
ironlake_edp_panel_vdd_on(intel_dp);
|
|
||||||
ironlake_edp_backlight_off(intel_dp);
|
ironlake_edp_backlight_off(intel_dp);
|
||||||
intel_dp_sink_dpms(intel_dp, DRM_MODE_DPMS_OFF);
|
intel_dp_sink_dpms(intel_dp, DRM_MODE_DPMS_OFF);
|
||||||
ironlake_edp_panel_off(intel_dp);
|
ironlake_edp_panel_off(intel_dp);
|
||||||
@@ -1942,18 +1945,6 @@ intel_dp_get_link_status(struct intel_dp *intel_dp, uint8_t link_status[DP_LINK_
|
|||||||
DP_LINK_STATUS_SIZE);
|
DP_LINK_STATUS_SIZE);
|
||||||
}
|
}
|
||||||
|
|
||||||
#if 0
|
|
||||||
static char *voltage_names[] = {
|
|
||||||
"0.4V", "0.6V", "0.8V", "1.2V"
|
|
||||||
};
|
|
||||||
static char *pre_emph_names[] = {
|
|
||||||
"0dB", "3.5dB", "6dB", "9.5dB"
|
|
||||||
};
|
|
||||||
static char *link_train_names[] = {
|
|
||||||
"pattern 1", "pattern 2", "idle", "off"
|
|
||||||
};
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* These are source-specific values; current Intel hardware supports
|
* These are source-specific values; current Intel hardware supports
|
||||||
* a maximum voltage of 800mV and a maximum pre-emphasis of 6dB
|
* a maximum voltage of 800mV and a maximum pre-emphasis of 6dB
|
||||||
@@ -3083,9 +3074,12 @@ intel_dp_detect(struct drm_connector *connector, bool force)
|
|||||||
struct intel_digital_port *intel_dig_port = dp_to_dig_port(intel_dp);
|
struct intel_digital_port *intel_dig_port = dp_to_dig_port(intel_dp);
|
||||||
struct intel_encoder *intel_encoder = &intel_dig_port->base;
|
struct intel_encoder *intel_encoder = &intel_dig_port->base;
|
||||||
struct drm_device *dev = connector->dev;
|
struct drm_device *dev = connector->dev;
|
||||||
|
struct drm_i915_private *dev_priv = dev->dev_private;
|
||||||
enum drm_connector_status status;
|
enum drm_connector_status status;
|
||||||
struct edid *edid = NULL;
|
struct edid *edid = NULL;
|
||||||
|
|
||||||
|
intel_runtime_pm_get(dev_priv);
|
||||||
|
|
||||||
DRM_DEBUG_KMS("[CONNECTOR:%d:%s]\n",
|
DRM_DEBUG_KMS("[CONNECTOR:%d:%s]\n",
|
||||||
connector->base.id, drm_get_connector_name(connector));
|
connector->base.id, drm_get_connector_name(connector));
|
||||||
|
|
||||||
@@ -3097,7 +3091,7 @@ intel_dp_detect(struct drm_connector *connector, bool force)
|
|||||||
status = g4x_dp_detect(intel_dp);
|
status = g4x_dp_detect(intel_dp);
|
||||||
|
|
||||||
if (status != connector_status_connected)
|
if (status != connector_status_connected)
|
||||||
return status;
|
goto out;
|
||||||
|
|
||||||
intel_dp_probe_oui(intel_dp);
|
intel_dp_probe_oui(intel_dp);
|
||||||
|
|
||||||
@@ -3113,7 +3107,11 @@ intel_dp_detect(struct drm_connector *connector, bool force)
|
|||||||
|
|
||||||
if (intel_encoder->type != INTEL_OUTPUT_EDP)
|
if (intel_encoder->type != INTEL_OUTPUT_EDP)
|
||||||
intel_encoder->type = INTEL_OUTPUT_DISPLAYPORT;
|
intel_encoder->type = INTEL_OUTPUT_DISPLAYPORT;
|
||||||
return connector_status_connected;
|
status = connector_status_connected;
|
||||||
|
|
||||||
|
out:
|
||||||
|
intel_runtime_pm_put(dev_priv);
|
||||||
|
return status;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int intel_dp_get_modes(struct drm_connector *connector)
|
static int intel_dp_get_modes(struct drm_connector *connector)
|
||||||
|
@@ -155,6 +155,7 @@ struct intel_encoder {
|
|||||||
|
|
||||||
struct intel_panel {
|
struct intel_panel {
|
||||||
struct drm_display_mode *fixed_mode;
|
struct drm_display_mode *fixed_mode;
|
||||||
|
struct drm_display_mode *downclock_mode;
|
||||||
int fitting_mode;
|
int fitting_mode;
|
||||||
|
|
||||||
/* backlight */
|
/* backlight */
|
||||||
@@ -454,7 +455,7 @@ struct intel_hdmi {
|
|||||||
bool rgb_quant_range_selectable;
|
bool rgb_quant_range_selectable;
|
||||||
void (*write_infoframe)(struct drm_encoder *encoder,
|
void (*write_infoframe)(struct drm_encoder *encoder,
|
||||||
enum hdmi_infoframe_type type,
|
enum hdmi_infoframe_type type,
|
||||||
const uint8_t *frame, ssize_t len);
|
const void *frame, ssize_t len);
|
||||||
void (*set_infoframes)(struct drm_encoder *encoder,
|
void (*set_infoframes)(struct drm_encoder *encoder,
|
||||||
struct drm_display_mode *adjusted_mode);
|
struct drm_display_mode *adjusted_mode);
|
||||||
};
|
};
|
||||||
@@ -612,7 +613,8 @@ void intel_ddi_disable_transcoder_func(struct drm_i915_private *dev_priv,
|
|||||||
void intel_ddi_enable_pipe_clock(struct intel_crtc *intel_crtc);
|
void intel_ddi_enable_pipe_clock(struct intel_crtc *intel_crtc);
|
||||||
void intel_ddi_disable_pipe_clock(struct intel_crtc *intel_crtc);
|
void intel_ddi_disable_pipe_clock(struct intel_crtc *intel_crtc);
|
||||||
void intel_ddi_setup_hw_pll_state(struct drm_device *dev);
|
void intel_ddi_setup_hw_pll_state(struct drm_device *dev);
|
||||||
bool intel_ddi_pll_mode_set(struct drm_crtc *crtc);
|
bool intel_ddi_pll_select(struct intel_crtc *crtc);
|
||||||
|
void intel_ddi_pll_enable(struct intel_crtc *crtc);
|
||||||
void intel_ddi_put_crtc_pll(struct drm_crtc *crtc);
|
void intel_ddi_put_crtc_pll(struct drm_crtc *crtc);
|
||||||
void intel_ddi_set_pipe_settings(struct drm_crtc *crtc);
|
void intel_ddi_set_pipe_settings(struct drm_crtc *crtc);
|
||||||
void intel_ddi_prepare_link_retrain(struct drm_encoder *encoder);
|
void intel_ddi_prepare_link_retrain(struct drm_encoder *encoder);
|
||||||
@@ -702,7 +704,6 @@ void
|
|||||||
ironlake_check_encoder_dotclock(const struct intel_crtc_config *pipe_config,
|
ironlake_check_encoder_dotclock(const struct intel_crtc_config *pipe_config,
|
||||||
int dotclock);
|
int dotclock);
|
||||||
bool intel_crtc_active(struct drm_crtc *crtc);
|
bool intel_crtc_active(struct drm_crtc *crtc);
|
||||||
void i915_disable_vga_mem(struct drm_device *dev);
|
|
||||||
void hsw_enable_ips(struct intel_crtc *crtc);
|
void hsw_enable_ips(struct intel_crtc *crtc);
|
||||||
void hsw_disable_ips(struct intel_crtc *crtc);
|
void hsw_disable_ips(struct intel_crtc *crtc);
|
||||||
void intel_display_set_init_power(struct drm_device *dev, bool enable);
|
void intel_display_set_init_power(struct drm_device *dev, bool enable);
|
||||||
@@ -823,7 +824,10 @@ void intel_panel_disable_backlight(struct intel_connector *connector);
|
|||||||
void intel_panel_destroy_backlight(struct drm_connector *connector);
|
void intel_panel_destroy_backlight(struct drm_connector *connector);
|
||||||
void intel_panel_init_backlight_funcs(struct drm_device *dev);
|
void intel_panel_init_backlight_funcs(struct drm_device *dev);
|
||||||
enum drm_connector_status intel_panel_detect(struct drm_device *dev);
|
enum drm_connector_status intel_panel_detect(struct drm_device *dev);
|
||||||
|
extern struct drm_display_mode *intel_find_panel_downclock(
|
||||||
|
struct drm_device *dev,
|
||||||
|
struct drm_display_mode *fixed_mode,
|
||||||
|
struct drm_connector *connector);
|
||||||
|
|
||||||
/* intel_pm.c */
|
/* intel_pm.c */
|
||||||
void intel_init_clock_gating(struct drm_device *dev);
|
void intel_init_clock_gating(struct drm_device *dev);
|
||||||
@@ -858,6 +862,10 @@ void gen6_rps_idle(struct drm_i915_private *dev_priv);
|
|||||||
void gen6_rps_boost(struct drm_i915_private *dev_priv);
|
void gen6_rps_boost(struct drm_i915_private *dev_priv);
|
||||||
void intel_aux_display_runtime_get(struct drm_i915_private *dev_priv);
|
void intel_aux_display_runtime_get(struct drm_i915_private *dev_priv);
|
||||||
void intel_aux_display_runtime_put(struct drm_i915_private *dev_priv);
|
void intel_aux_display_runtime_put(struct drm_i915_private *dev_priv);
|
||||||
|
void intel_runtime_pm_get(struct drm_i915_private *dev_priv);
|
||||||
|
void intel_runtime_pm_put(struct drm_i915_private *dev_priv);
|
||||||
|
void intel_init_runtime_pm(struct drm_i915_private *dev_priv);
|
||||||
|
void intel_fini_runtime_pm(struct drm_i915_private *dev_priv);
|
||||||
void ilk_wm_get_hw_state(struct drm_device *dev);
|
void ilk_wm_get_hw_state(struct drm_device *dev);
|
||||||
|
|
||||||
|
|
||||||
|
@@ -37,49 +37,18 @@
|
|||||||
static const struct intel_dsi_device intel_dsi_devices[] = {
|
static const struct intel_dsi_device intel_dsi_devices[] = {
|
||||||
};
|
};
|
||||||
|
|
||||||
|
static void band_gap_reset(struct drm_i915_private *dev_priv)
|
||||||
static void vlv_cck_modify(struct drm_i915_private *dev_priv, u32 reg, u32 val,
|
|
||||||
u32 mask)
|
|
||||||
{
|
|
||||||
u32 tmp = vlv_cck_read(dev_priv, reg);
|
|
||||||
tmp &= ~mask;
|
|
||||||
tmp |= val;
|
|
||||||
vlv_cck_write(dev_priv, reg, tmp);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void band_gap_wa(struct drm_i915_private *dev_priv)
|
|
||||||
{
|
{
|
||||||
mutex_lock(&dev_priv->dpio_lock);
|
mutex_lock(&dev_priv->dpio_lock);
|
||||||
|
|
||||||
/* Enable bandgap fix in GOP driver */
|
vlv_flisdsi_write(dev_priv, 0x08, 0x0001);
|
||||||
vlv_cck_modify(dev_priv, 0x6D, 0x00010000, 0x00030000);
|
vlv_flisdsi_write(dev_priv, 0x0F, 0x0005);
|
||||||
msleep(20);
|
vlv_flisdsi_write(dev_priv, 0x0F, 0x0025);
|
||||||
vlv_cck_modify(dev_priv, 0x6E, 0x00010000, 0x00030000);
|
udelay(150);
|
||||||
msleep(20);
|
vlv_flisdsi_write(dev_priv, 0x0F, 0x0000);
|
||||||
vlv_cck_modify(dev_priv, 0x6F, 0x00010000, 0x00030000);
|
vlv_flisdsi_write(dev_priv, 0x08, 0x0000);
|
||||||
msleep(20);
|
|
||||||
vlv_cck_modify(dev_priv, 0x00, 0x00008000, 0x00008000);
|
|
||||||
msleep(20);
|
|
||||||
vlv_cck_modify(dev_priv, 0x00, 0x00000000, 0x00008000);
|
|
||||||
msleep(20);
|
|
||||||
|
|
||||||
/* Turn Display Trunk on */
|
|
||||||
vlv_cck_modify(dev_priv, 0x6B, 0x00020000, 0x00030000);
|
|
||||||
msleep(20);
|
|
||||||
|
|
||||||
vlv_cck_modify(dev_priv, 0x6C, 0x00020000, 0x00030000);
|
|
||||||
msleep(20);
|
|
||||||
|
|
||||||
vlv_cck_modify(dev_priv, 0x6D, 0x00020000, 0x00030000);
|
|
||||||
msleep(20);
|
|
||||||
vlv_cck_modify(dev_priv, 0x6E, 0x00020000, 0x00030000);
|
|
||||||
msleep(20);
|
|
||||||
vlv_cck_modify(dev_priv, 0x6F, 0x00020000, 0x00030000);
|
|
||||||
|
|
||||||
mutex_unlock(&dev_priv->dpio_lock);
|
mutex_unlock(&dev_priv->dpio_lock);
|
||||||
|
|
||||||
/* Need huge delay, otherwise clock is not stable */
|
|
||||||
msleep(100);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static struct intel_dsi *intel_attached_dsi(struct drm_connector *connector)
|
static struct intel_dsi *intel_attached_dsi(struct drm_connector *connector)
|
||||||
@@ -132,14 +101,47 @@ static void intel_dsi_pre_pll_enable(struct intel_encoder *encoder)
|
|||||||
vlv_enable_dsi_pll(encoder);
|
vlv_enable_dsi_pll(encoder);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void intel_dsi_device_ready(struct intel_encoder *encoder)
|
||||||
|
{
|
||||||
|
struct drm_i915_private *dev_priv = encoder->base.dev->dev_private;
|
||||||
|
struct intel_crtc *intel_crtc = to_intel_crtc(encoder->base.crtc);
|
||||||
|
int pipe = intel_crtc->pipe;
|
||||||
|
u32 val;
|
||||||
|
|
||||||
|
DRM_DEBUG_KMS("\n");
|
||||||
|
|
||||||
|
val = I915_READ(MIPI_PORT_CTRL(pipe));
|
||||||
|
I915_WRITE(MIPI_PORT_CTRL(pipe), val | LP_OUTPUT_HOLD);
|
||||||
|
usleep_range(1000, 1500);
|
||||||
|
I915_WRITE(MIPI_DEVICE_READY(pipe), DEVICE_READY | ULPS_STATE_EXIT);
|
||||||
|
usleep_range(2000, 2500);
|
||||||
|
I915_WRITE(MIPI_DEVICE_READY(pipe), DEVICE_READY);
|
||||||
|
usleep_range(2000, 2500);
|
||||||
|
I915_WRITE(MIPI_DEVICE_READY(pipe), 0x00);
|
||||||
|
usleep_range(2000, 2500);
|
||||||
|
I915_WRITE(MIPI_DEVICE_READY(pipe), DEVICE_READY);
|
||||||
|
usleep_range(2000, 2500);
|
||||||
|
}
|
||||||
static void intel_dsi_pre_enable(struct intel_encoder *encoder)
|
static void intel_dsi_pre_enable(struct intel_encoder *encoder)
|
||||||
{
|
{
|
||||||
|
struct intel_dsi *intel_dsi = enc_to_intel_dsi(&encoder->base);
|
||||||
|
|
||||||
DRM_DEBUG_KMS("\n");
|
DRM_DEBUG_KMS("\n");
|
||||||
|
|
||||||
|
if (intel_dsi->dev.dev_ops->panel_reset)
|
||||||
|
intel_dsi->dev.dev_ops->panel_reset(&intel_dsi->dev);
|
||||||
|
|
||||||
|
/* put device in ready state */
|
||||||
|
intel_dsi_device_ready(encoder);
|
||||||
|
|
||||||
|
if (intel_dsi->dev.dev_ops->send_otp_cmds)
|
||||||
|
intel_dsi->dev.dev_ops->send_otp_cmds(&intel_dsi->dev);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void intel_dsi_enable(struct intel_encoder *encoder)
|
static void intel_dsi_enable(struct intel_encoder *encoder)
|
||||||
{
|
{
|
||||||
struct drm_i915_private *dev_priv = encoder->base.dev->dev_private;
|
struct drm_device *dev = encoder->base.dev;
|
||||||
|
struct drm_i915_private *dev_priv = dev->dev_private;
|
||||||
struct intel_crtc *intel_crtc = to_intel_crtc(encoder->base.crtc);
|
struct intel_crtc *intel_crtc = to_intel_crtc(encoder->base.crtc);
|
||||||
struct intel_dsi *intel_dsi = enc_to_intel_dsi(&encoder->base);
|
struct intel_dsi *intel_dsi = enc_to_intel_dsi(&encoder->base);
|
||||||
int pipe = intel_crtc->pipe;
|
int pipe = intel_crtc->pipe;
|
||||||
@@ -147,41 +149,28 @@ static void intel_dsi_enable(struct intel_encoder *encoder)
|
|||||||
|
|
||||||
DRM_DEBUG_KMS("\n");
|
DRM_DEBUG_KMS("\n");
|
||||||
|
|
||||||
temp = I915_READ(MIPI_DEVICE_READY(pipe));
|
|
||||||
if ((temp & DEVICE_READY) == 0) {
|
|
||||||
temp &= ~ULPS_STATE_MASK;
|
|
||||||
I915_WRITE(MIPI_DEVICE_READY(pipe), temp | DEVICE_READY);
|
|
||||||
} else if (temp & ULPS_STATE_MASK) {
|
|
||||||
temp &= ~ULPS_STATE_MASK;
|
|
||||||
I915_WRITE(MIPI_DEVICE_READY(pipe), temp | ULPS_STATE_EXIT);
|
|
||||||
/*
|
|
||||||
* We need to ensure that there is a minimum of 1 ms time
|
|
||||||
* available before clearing the UPLS exit state.
|
|
||||||
*/
|
|
||||||
msleep(2);
|
|
||||||
I915_WRITE(MIPI_DEVICE_READY(pipe), temp);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (is_cmd_mode(intel_dsi))
|
if (is_cmd_mode(intel_dsi))
|
||||||
I915_WRITE(MIPI_MAX_RETURN_PKT_SIZE(pipe), 8 * 4);
|
I915_WRITE(MIPI_MAX_RETURN_PKT_SIZE(pipe), 8 * 4);
|
||||||
|
else {
|
||||||
if (is_vid_mode(intel_dsi)) {
|
|
||||||
msleep(20); /* XXX */
|
msleep(20); /* XXX */
|
||||||
dpi_send_cmd(intel_dsi, TURN_ON);
|
dpi_send_cmd(intel_dsi, TURN_ON);
|
||||||
msleep(100);
|
msleep(100);
|
||||||
|
|
||||||
/* assert ip_tg_enable signal */
|
/* assert ip_tg_enable signal */
|
||||||
temp = I915_READ(MIPI_PORT_CTRL(pipe));
|
temp = I915_READ(MIPI_PORT_CTRL(pipe)) & ~LANE_CONFIGURATION_MASK;
|
||||||
|
temp = temp | intel_dsi->port_bits;
|
||||||
I915_WRITE(MIPI_PORT_CTRL(pipe), temp | DPI_ENABLE);
|
I915_WRITE(MIPI_PORT_CTRL(pipe), temp | DPI_ENABLE);
|
||||||
POSTING_READ(MIPI_PORT_CTRL(pipe));
|
POSTING_READ(MIPI_PORT_CTRL(pipe));
|
||||||
}
|
}
|
||||||
|
|
||||||
intel_dsi->dev.dev_ops->enable(&intel_dsi->dev);
|
if (intel_dsi->dev.dev_ops->enable)
|
||||||
|
intel_dsi->dev.dev_ops->enable(&intel_dsi->dev);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void intel_dsi_disable(struct intel_encoder *encoder)
|
static void intel_dsi_disable(struct intel_encoder *encoder)
|
||||||
{
|
{
|
||||||
struct drm_i915_private *dev_priv = encoder->base.dev->dev_private;
|
struct drm_device *dev = encoder->base.dev;
|
||||||
|
struct drm_i915_private *dev_priv = dev->dev_private;
|
||||||
struct intel_crtc *intel_crtc = to_intel_crtc(encoder->base.crtc);
|
struct intel_crtc *intel_crtc = to_intel_crtc(encoder->base.crtc);
|
||||||
struct intel_dsi *intel_dsi = enc_to_intel_dsi(&encoder->base);
|
struct intel_dsi *intel_dsi = enc_to_intel_dsi(&encoder->base);
|
||||||
int pipe = intel_crtc->pipe;
|
int pipe = intel_crtc->pipe;
|
||||||
@@ -189,8 +178,6 @@ static void intel_dsi_disable(struct intel_encoder *encoder)
|
|||||||
|
|
||||||
DRM_DEBUG_KMS("\n");
|
DRM_DEBUG_KMS("\n");
|
||||||
|
|
||||||
intel_dsi->dev.dev_ops->disable(&intel_dsi->dev);
|
|
||||||
|
|
||||||
if (is_vid_mode(intel_dsi)) {
|
if (is_vid_mode(intel_dsi)) {
|
||||||
dpi_send_cmd(intel_dsi, SHUTDOWN);
|
dpi_send_cmd(intel_dsi, SHUTDOWN);
|
||||||
msleep(10);
|
msleep(10);
|
||||||
@@ -203,20 +190,54 @@ static void intel_dsi_disable(struct intel_encoder *encoder)
|
|||||||
msleep(2);
|
msleep(2);
|
||||||
}
|
}
|
||||||
|
|
||||||
temp = I915_READ(MIPI_DEVICE_READY(pipe));
|
/* if disable packets are sent before sending shutdown packet then in
|
||||||
if (temp & DEVICE_READY) {
|
* some next enable sequence send turn on packet error is observed */
|
||||||
temp &= ~DEVICE_READY;
|
if (intel_dsi->dev.dev_ops->disable)
|
||||||
temp &= ~ULPS_STATE_MASK;
|
intel_dsi->dev.dev_ops->disable(&intel_dsi->dev);
|
||||||
I915_WRITE(MIPI_DEVICE_READY(pipe), temp);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void intel_dsi_post_disable(struct intel_encoder *encoder)
|
static void intel_dsi_clear_device_ready(struct intel_encoder *encoder)
|
||||||
{
|
{
|
||||||
|
struct drm_i915_private *dev_priv = encoder->base.dev->dev_private;
|
||||||
|
struct intel_crtc *intel_crtc = to_intel_crtc(encoder->base.crtc);
|
||||||
|
int pipe = intel_crtc->pipe;
|
||||||
|
u32 val;
|
||||||
|
|
||||||
DRM_DEBUG_KMS("\n");
|
DRM_DEBUG_KMS("\n");
|
||||||
|
|
||||||
|
I915_WRITE(MIPI_DEVICE_READY(pipe), ULPS_STATE_ENTER);
|
||||||
|
usleep_range(2000, 2500);
|
||||||
|
|
||||||
|
I915_WRITE(MIPI_DEVICE_READY(pipe), ULPS_STATE_EXIT);
|
||||||
|
usleep_range(2000, 2500);
|
||||||
|
|
||||||
|
I915_WRITE(MIPI_DEVICE_READY(pipe), ULPS_STATE_ENTER);
|
||||||
|
usleep_range(2000, 2500);
|
||||||
|
|
||||||
|
val = I915_READ(MIPI_PORT_CTRL(pipe));
|
||||||
|
I915_WRITE(MIPI_PORT_CTRL(pipe), val & ~LP_OUTPUT_HOLD);
|
||||||
|
usleep_range(1000, 1500);
|
||||||
|
|
||||||
|
if (wait_for(((I915_READ(MIPI_PORT_CTRL(pipe)) & AFE_LATCHOUT)
|
||||||
|
== 0x00000), 30))
|
||||||
|
DRM_ERROR("DSI LP not going Low\n");
|
||||||
|
|
||||||
|
I915_WRITE(MIPI_DEVICE_READY(pipe), 0x00);
|
||||||
|
usleep_range(2000, 2500);
|
||||||
|
|
||||||
vlv_disable_dsi_pll(encoder);
|
vlv_disable_dsi_pll(encoder);
|
||||||
}
|
}
|
||||||
|
static void intel_dsi_post_disable(struct intel_encoder *encoder)
|
||||||
|
{
|
||||||
|
struct intel_dsi *intel_dsi = enc_to_intel_dsi(&encoder->base);
|
||||||
|
|
||||||
|
DRM_DEBUG_KMS("\n");
|
||||||
|
|
||||||
|
intel_dsi_clear_device_ready(encoder);
|
||||||
|
|
||||||
|
if (intel_dsi->dev.dev_ops->disable_panel_power)
|
||||||
|
intel_dsi->dev.dev_ops->disable_panel_power(&intel_dsi->dev);
|
||||||
|
}
|
||||||
|
|
||||||
static bool intel_dsi_get_hw_state(struct intel_encoder *encoder,
|
static bool intel_dsi_get_hw_state(struct intel_encoder *encoder,
|
||||||
enum pipe *pipe)
|
enum pipe *pipe)
|
||||||
@@ -353,11 +374,8 @@ static void intel_dsi_mode_set(struct intel_encoder *intel_encoder)
|
|||||||
|
|
||||||
DRM_DEBUG_KMS("pipe %c\n", pipe_name(pipe));
|
DRM_DEBUG_KMS("pipe %c\n", pipe_name(pipe));
|
||||||
|
|
||||||
/* Update the DSI PLL */
|
|
||||||
vlv_enable_dsi_pll(intel_encoder);
|
|
||||||
|
|
||||||
/* XXX: Location of the call */
|
/* XXX: Location of the call */
|
||||||
band_gap_wa(dev_priv);
|
band_gap_reset(dev_priv);
|
||||||
|
|
||||||
/* escape clock divider, 20MHz, shared for A and C. device ready must be
|
/* escape clock divider, 20MHz, shared for A and C. device ready must be
|
||||||
* off when doing this! txclkesc? */
|
* off when doing this! txclkesc? */
|
||||||
@@ -374,11 +392,7 @@ static void intel_dsi_mode_set(struct intel_encoder *intel_encoder)
|
|||||||
I915_WRITE(MIPI_INTR_STAT(pipe), 0xffffffff);
|
I915_WRITE(MIPI_INTR_STAT(pipe), 0xffffffff);
|
||||||
I915_WRITE(MIPI_INTR_EN(pipe), 0xffffffff);
|
I915_WRITE(MIPI_INTR_EN(pipe), 0xffffffff);
|
||||||
|
|
||||||
I915_WRITE(MIPI_DPHY_PARAM(pipe),
|
I915_WRITE(MIPI_DPHY_PARAM(pipe), intel_dsi->dphy_reg);
|
||||||
0x3c << EXIT_ZERO_COUNT_SHIFT |
|
|
||||||
0x1f << TRAIL_COUNT_SHIFT |
|
|
||||||
0xc5 << CLK_ZERO_COUNT_SHIFT |
|
|
||||||
0x1f << PREPARE_COUNT_SHIFT);
|
|
||||||
|
|
||||||
I915_WRITE(MIPI_DPI_RESOLUTION(pipe),
|
I915_WRITE(MIPI_DPI_RESOLUTION(pipe),
|
||||||
adjusted_mode->vdisplay << VERTICAL_ADDRESS_SHIFT |
|
adjusted_mode->vdisplay << VERTICAL_ADDRESS_SHIFT |
|
||||||
@@ -426,9 +440,9 @@ static void intel_dsi_mode_set(struct intel_encoder *intel_encoder)
|
|||||||
adjusted_mode->htotal,
|
adjusted_mode->htotal,
|
||||||
bpp, intel_dsi->lane_count) + 1);
|
bpp, intel_dsi->lane_count) + 1);
|
||||||
}
|
}
|
||||||
I915_WRITE(MIPI_LP_RX_TIMEOUT(pipe), 8309); /* max */
|
I915_WRITE(MIPI_LP_RX_TIMEOUT(pipe), intel_dsi->lp_rx_timeout);
|
||||||
I915_WRITE(MIPI_TURN_AROUND_TIMEOUT(pipe), 0x14); /* max */
|
I915_WRITE(MIPI_TURN_AROUND_TIMEOUT(pipe), intel_dsi->turn_arnd_val);
|
||||||
I915_WRITE(MIPI_DEVICE_RESET_TIMER(pipe), 0xffff); /* max */
|
I915_WRITE(MIPI_DEVICE_RESET_TIMER(pipe), intel_dsi->rst_timer_val);
|
||||||
|
|
||||||
/* dphy stuff */
|
/* dphy stuff */
|
||||||
|
|
||||||
@@ -443,29 +457,31 @@ static void intel_dsi_mode_set(struct intel_encoder *intel_encoder)
|
|||||||
*
|
*
|
||||||
* XXX: write MIPI_STOP_STATE_STALL?
|
* XXX: write MIPI_STOP_STATE_STALL?
|
||||||
*/
|
*/
|
||||||
I915_WRITE(MIPI_HIGH_LOW_SWITCH_COUNT(pipe), 0x46);
|
I915_WRITE(MIPI_HIGH_LOW_SWITCH_COUNT(pipe),
|
||||||
|
intel_dsi->hs_to_lp_count);
|
||||||
|
|
||||||
/* XXX: low power clock equivalence in terms of byte clock. the number
|
/* XXX: low power clock equivalence in terms of byte clock. the number
|
||||||
* of byte clocks occupied in one low power clock. based on txbyteclkhs
|
* of byte clocks occupied in one low power clock. based on txbyteclkhs
|
||||||
* and txclkesc. txclkesc time / txbyteclk time * (105 +
|
* and txclkesc. txclkesc time / txbyteclk time * (105 +
|
||||||
* MIPI_STOP_STATE_STALL) / 105.???
|
* MIPI_STOP_STATE_STALL) / 105.???
|
||||||
*/
|
*/
|
||||||
I915_WRITE(MIPI_LP_BYTECLK(pipe), 4);
|
I915_WRITE(MIPI_LP_BYTECLK(pipe), intel_dsi->lp_byte_clk);
|
||||||
|
|
||||||
/* the bw essential for transmitting 16 long packets containing 252
|
/* the bw essential for transmitting 16 long packets containing 252
|
||||||
* bytes meant for dcs write memory command is programmed in this
|
* bytes meant for dcs write memory command is programmed in this
|
||||||
* register in terms of byte clocks. based on dsi transfer rate and the
|
* register in terms of byte clocks. based on dsi transfer rate and the
|
||||||
* number of lanes configured the time taken to transmit 16 long packets
|
* number of lanes configured the time taken to transmit 16 long packets
|
||||||
* in a dsi stream varies. */
|
* in a dsi stream varies. */
|
||||||
I915_WRITE(MIPI_DBI_BW_CTRL(pipe), 0x820);
|
I915_WRITE(MIPI_DBI_BW_CTRL(pipe), intel_dsi->bw_timer);
|
||||||
|
|
||||||
I915_WRITE(MIPI_CLK_LANE_SWITCH_TIME_CNT(pipe),
|
I915_WRITE(MIPI_CLK_LANE_SWITCH_TIME_CNT(pipe),
|
||||||
0xa << LP_HS_SSW_CNT_SHIFT |
|
intel_dsi->clk_lp_to_hs_count << LP_HS_SSW_CNT_SHIFT |
|
||||||
0x14 << HS_LP_PWR_SW_CNT_SHIFT);
|
intel_dsi->clk_hs_to_lp_count << HS_LP_PWR_SW_CNT_SHIFT);
|
||||||
|
|
||||||
if (is_vid_mode(intel_dsi))
|
if (is_vid_mode(intel_dsi))
|
||||||
I915_WRITE(MIPI_VIDEO_MODE_FORMAT(pipe),
|
I915_WRITE(MIPI_VIDEO_MODE_FORMAT(pipe),
|
||||||
intel_dsi->video_mode_format);
|
intel_dsi->video_frmt_cfg_bits |
|
||||||
|
intel_dsi->video_mode_format);
|
||||||
}
|
}
|
||||||
|
|
||||||
static enum drm_connector_status
|
static enum drm_connector_status
|
||||||
|
@@ -39,6 +39,13 @@ struct intel_dsi_device {
|
|||||||
struct intel_dsi_dev_ops {
|
struct intel_dsi_dev_ops {
|
||||||
bool (*init)(struct intel_dsi_device *dsi);
|
bool (*init)(struct intel_dsi_device *dsi);
|
||||||
|
|
||||||
|
void (*panel_reset)(struct intel_dsi_device *dsi);
|
||||||
|
|
||||||
|
void (*disable_panel_power)(struct intel_dsi_device *dsi);
|
||||||
|
|
||||||
|
/* one time programmable commands if needed */
|
||||||
|
void (*send_otp_cmds)(struct intel_dsi_device *dsi);
|
||||||
|
|
||||||
/* This callback must be able to assume DSI commands can be sent */
|
/* This callback must be able to assume DSI commands can be sent */
|
||||||
void (*enable)(struct intel_dsi_device *dsi);
|
void (*enable)(struct intel_dsi_device *dsi);
|
||||||
|
|
||||||
@@ -89,6 +96,20 @@ struct intel_dsi {
|
|||||||
|
|
||||||
/* eot for MIPI_EOT_DISABLE register */
|
/* eot for MIPI_EOT_DISABLE register */
|
||||||
u32 eot_disable;
|
u32 eot_disable;
|
||||||
|
|
||||||
|
u32 port_bits;
|
||||||
|
u32 bw_timer;
|
||||||
|
u32 dphy_reg;
|
||||||
|
u32 video_frmt_cfg_bits;
|
||||||
|
u16 lp_byte_clk;
|
||||||
|
|
||||||
|
/* timeouts in byte clocks */
|
||||||
|
u16 lp_rx_timeout;
|
||||||
|
u16 turn_arnd_val;
|
||||||
|
u16 rst_timer_val;
|
||||||
|
u16 hs_to_lp_count;
|
||||||
|
u16 clk_lp_to_hs_count;
|
||||||
|
u16 clk_hs_to_lp_count;
|
||||||
};
|
};
|
||||||
|
|
||||||
static inline struct intel_dsi *enc_to_intel_dsi(struct drm_encoder *encoder)
|
static inline struct intel_dsi *enc_to_intel_dsi(struct drm_encoder *encoder)
|
||||||
|
@@ -50,6 +50,8 @@ static const u32 lfsr_converts[] = {
|
|||||||
71, 35 /* 91 - 92 */
|
71, 35 /* 91 - 92 */
|
||||||
};
|
};
|
||||||
|
|
||||||
|
#ifdef DSI_CLK_FROM_RR
|
||||||
|
|
||||||
static u32 dsi_rr_formula(const struct drm_display_mode *mode,
|
static u32 dsi_rr_formula(const struct drm_display_mode *mode,
|
||||||
int pixel_format, int video_mode_format,
|
int pixel_format, int video_mode_format,
|
||||||
int lane_count, bool eotp)
|
int lane_count, bool eotp)
|
||||||
@@ -121,7 +123,7 @@ static u32 dsi_rr_formula(const struct drm_display_mode *mode,
|
|||||||
|
|
||||||
/* the dsi clock is divided by 2 in the hardware to get dsi ddr clock */
|
/* the dsi clock is divided by 2 in the hardware to get dsi ddr clock */
|
||||||
dsi_bit_clock_hz = bytes_per_x_frames_x_lanes * 8;
|
dsi_bit_clock_hz = bytes_per_x_frames_x_lanes * 8;
|
||||||
dsi_clk = dsi_bit_clock_hz / (1000 * 1000);
|
dsi_clk = dsi_bit_clock_hz / 1000;
|
||||||
|
|
||||||
if (eotp && video_mode_format == VIDEO_MODE_BURST)
|
if (eotp && video_mode_format == VIDEO_MODE_BURST)
|
||||||
dsi_clk *= 2;
|
dsi_clk *= 2;
|
||||||
@@ -129,64 +131,37 @@ static u32 dsi_rr_formula(const struct drm_display_mode *mode,
|
|||||||
return dsi_clk;
|
return dsi_clk;
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef MNP_FROM_TABLE
|
#else
|
||||||
|
|
||||||
struct dsi_clock_table {
|
/* Get DSI clock from pixel clock */
|
||||||
u32 freq;
|
static u32 dsi_clk_from_pclk(const struct drm_display_mode *mode,
|
||||||
u8 m;
|
int pixel_format, int lane_count)
|
||||||
u8 p;
|
|
||||||
};
|
|
||||||
|
|
||||||
static const struct dsi_clock_table dsi_clk_tbl[] = {
|
|
||||||
{300, 72, 6}, {313, 75, 6}, {323, 78, 6}, {333, 80, 6},
|
|
||||||
{343, 82, 6}, {353, 85, 6}, {363, 87, 6}, {373, 90, 6},
|
|
||||||
{383, 92, 6}, {390, 78, 5}, {393, 79, 5}, {400, 80, 5},
|
|
||||||
{401, 80, 5}, {402, 80, 5}, {403, 81, 5}, {404, 81, 5},
|
|
||||||
{405, 81, 5}, {406, 81, 5}, {407, 81, 5}, {408, 82, 5},
|
|
||||||
{409, 82, 5}, {410, 82, 5}, {411, 82, 5}, {412, 82, 5},
|
|
||||||
{413, 83, 5}, {414, 83, 5}, {415, 83, 5}, {416, 83, 5},
|
|
||||||
{417, 83, 5}, {418, 84, 5}, {419, 84, 5}, {420, 84, 5},
|
|
||||||
{430, 86, 5}, {440, 88, 5}, {450, 90, 5}, {460, 92, 5},
|
|
||||||
{470, 75, 4}, {480, 77, 4}, {490, 78, 4}, {500, 80, 4},
|
|
||||||
{510, 82, 4}, {520, 83, 4}, {530, 85, 4}, {540, 86, 4},
|
|
||||||
{550, 88, 4}, {560, 90, 4}, {570, 91, 4}, {580, 70, 3},
|
|
||||||
{590, 71, 3}, {600, 72, 3}, {610, 73, 3}, {620, 74, 3},
|
|
||||||
{630, 76, 3}, {640, 77, 3}, {650, 78, 3}, {660, 79, 3},
|
|
||||||
{670, 80, 3}, {680, 82, 3}, {690, 83, 3}, {700, 84, 3},
|
|
||||||
{710, 85, 3}, {720, 86, 3}, {730, 88, 3}, {740, 89, 3},
|
|
||||||
{750, 90, 3}, {760, 91, 3}, {770, 92, 3}, {780, 62, 2},
|
|
||||||
{790, 63, 2}, {800, 64, 2}, {880, 70, 2}, {900, 72, 2},
|
|
||||||
{1000, 80, 2}, /* dsi clock frequency in Mhz*/
|
|
||||||
};
|
|
||||||
|
|
||||||
static int dsi_calc_mnp(u32 dsi_clk, struct dsi_mnp *dsi_mnp)
|
|
||||||
{
|
{
|
||||||
unsigned int i;
|
u32 dsi_clk_khz;
|
||||||
u8 m;
|
u32 bpp;
|
||||||
u8 n;
|
|
||||||
u8 p;
|
|
||||||
u32 m_seed;
|
|
||||||
|
|
||||||
if (dsi_clk < 300 || dsi_clk > 1000)
|
switch (pixel_format) {
|
||||||
return -ECHRNG;
|
default:
|
||||||
|
case VID_MODE_FORMAT_RGB888:
|
||||||
for (i = 0; i <= ARRAY_SIZE(dsi_clk_tbl); i++) {
|
case VID_MODE_FORMAT_RGB666_LOOSE:
|
||||||
if (dsi_clk_tbl[i].freq > dsi_clk)
|
bpp = 24;
|
||||||
break;
|
break;
|
||||||
|
case VID_MODE_FORMAT_RGB666:
|
||||||
|
bpp = 18;
|
||||||
|
break;
|
||||||
|
case VID_MODE_FORMAT_RGB565:
|
||||||
|
bpp = 16;
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
m = dsi_clk_tbl[i].m;
|
/* DSI data rate = pixel clock * bits per pixel / lane count
|
||||||
p = dsi_clk_tbl[i].p;
|
pixel clock is converted from KHz to Hz */
|
||||||
m_seed = lfsr_converts[m - 62];
|
dsi_clk_khz = DIV_ROUND_CLOSEST(mode->clock * bpp, lane_count);
|
||||||
n = 1;
|
|
||||||
dsi_mnp->dsi_pll_ctrl = 1 << (DSI_PLL_P1_POST_DIV_SHIFT + p - 2);
|
|
||||||
dsi_mnp->dsi_pll_div = (n - 1) << DSI_PLL_N1_DIV_SHIFT |
|
|
||||||
m_seed << DSI_PLL_M1_DIV_SHIFT;
|
|
||||||
|
|
||||||
return 0;
|
return dsi_clk_khz;
|
||||||
}
|
}
|
||||||
|
|
||||||
#else
|
#endif
|
||||||
|
|
||||||
static int dsi_calc_mnp(u32 dsi_clk, struct dsi_mnp *dsi_mnp)
|
static int dsi_calc_mnp(u32 dsi_clk, struct dsi_mnp *dsi_mnp)
|
||||||
{
|
{
|
||||||
@@ -194,36 +169,47 @@ static int dsi_calc_mnp(u32 dsi_clk, struct dsi_mnp *dsi_mnp)
|
|||||||
u32 ref_clk;
|
u32 ref_clk;
|
||||||
u32 error;
|
u32 error;
|
||||||
u32 tmp_error;
|
u32 tmp_error;
|
||||||
u32 target_dsi_clk;
|
int target_dsi_clk;
|
||||||
u32 calc_dsi_clk;
|
int calc_dsi_clk;
|
||||||
u32 calc_m;
|
u32 calc_m;
|
||||||
u32 calc_p;
|
u32 calc_p;
|
||||||
u32 m_seed;
|
u32 m_seed;
|
||||||
|
|
||||||
if (dsi_clk < 300 || dsi_clk > 1150) {
|
/* dsi_clk is expected in KHZ */
|
||||||
|
if (dsi_clk < 300000 || dsi_clk > 1150000) {
|
||||||
DRM_ERROR("DSI CLK Out of Range\n");
|
DRM_ERROR("DSI CLK Out of Range\n");
|
||||||
return -ECHRNG;
|
return -ECHRNG;
|
||||||
}
|
}
|
||||||
|
|
||||||
ref_clk = 25000;
|
ref_clk = 25000;
|
||||||
target_dsi_clk = dsi_clk * 1000;
|
target_dsi_clk = dsi_clk;
|
||||||
error = 0xFFFFFFFF;
|
error = 0xFFFFFFFF;
|
||||||
|
tmp_error = 0xFFFFFFFF;
|
||||||
calc_m = 0;
|
calc_m = 0;
|
||||||
calc_p = 0;
|
calc_p = 0;
|
||||||
|
|
||||||
for (m = 62; m <= 92; m++) {
|
for (m = 62; m <= 92; m++) {
|
||||||
for (p = 2; p <= 6; p++) {
|
for (p = 2; p <= 6; p++) {
|
||||||
|
/* Find the optimal m and p divisors
|
||||||
|
with minimal error +/- the required clock */
|
||||||
calc_dsi_clk = (m * ref_clk) / p;
|
calc_dsi_clk = (m * ref_clk) / p;
|
||||||
if (calc_dsi_clk >= target_dsi_clk) {
|
if (calc_dsi_clk == target_dsi_clk) {
|
||||||
tmp_error = calc_dsi_clk - target_dsi_clk;
|
calc_m = m;
|
||||||
if (tmp_error < error) {
|
calc_p = p;
|
||||||
error = tmp_error;
|
error = 0;
|
||||||
calc_m = m;
|
break;
|
||||||
calc_p = p;
|
} else
|
||||||
}
|
tmp_error = abs(target_dsi_clk - calc_dsi_clk);
|
||||||
|
|
||||||
|
if (tmp_error < error) {
|
||||||
|
error = tmp_error;
|
||||||
|
calc_m = m;
|
||||||
|
calc_p = p;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (error == 0)
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
m_seed = lfsr_converts[calc_m - 62];
|
m_seed = lfsr_converts[calc_m - 62];
|
||||||
@@ -235,8 +221,6 @@ static int dsi_calc_mnp(u32 dsi_clk, struct dsi_mnp *dsi_mnp)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* XXX: The muxing and gating is hard coded for now. Need to add support for
|
* XXX: The muxing and gating is hard coded for now. Need to add support for
|
||||||
* sharing PLLs with two DSI outputs.
|
* sharing PLLs with two DSI outputs.
|
||||||
@@ -251,9 +235,8 @@ static void vlv_configure_dsi_pll(struct intel_encoder *encoder)
|
|||||||
struct dsi_mnp dsi_mnp;
|
struct dsi_mnp dsi_mnp;
|
||||||
u32 dsi_clk;
|
u32 dsi_clk;
|
||||||
|
|
||||||
dsi_clk = dsi_rr_formula(mode, intel_dsi->pixel_format,
|
dsi_clk = dsi_clk_from_pclk(mode, intel_dsi->pixel_format,
|
||||||
intel_dsi->video_mode_format,
|
intel_dsi->lane_count);
|
||||||
intel_dsi->lane_count, !intel_dsi->eot_disable);
|
|
||||||
|
|
||||||
ret = dsi_calc_mnp(dsi_clk, &dsi_mnp);
|
ret = dsi_calc_mnp(dsi_clk, &dsi_mnp);
|
||||||
if (ret) {
|
if (ret) {
|
||||||
|
@@ -130,9 +130,9 @@ static u32 hsw_infoframe_data_reg(enum hdmi_infoframe_type type,
|
|||||||
|
|
||||||
static void g4x_write_infoframe(struct drm_encoder *encoder,
|
static void g4x_write_infoframe(struct drm_encoder *encoder,
|
||||||
enum hdmi_infoframe_type type,
|
enum hdmi_infoframe_type type,
|
||||||
const uint8_t *frame, ssize_t len)
|
const void *frame, ssize_t len)
|
||||||
{
|
{
|
||||||
uint32_t *data = (uint32_t *)frame;
|
const uint32_t *data = frame;
|
||||||
struct drm_device *dev = encoder->dev;
|
struct drm_device *dev = encoder->dev;
|
||||||
struct drm_i915_private *dev_priv = dev->dev_private;
|
struct drm_i915_private *dev_priv = dev->dev_private;
|
||||||
u32 val = I915_READ(VIDEO_DIP_CTL);
|
u32 val = I915_READ(VIDEO_DIP_CTL);
|
||||||
@@ -167,9 +167,9 @@ static void g4x_write_infoframe(struct drm_encoder *encoder,
|
|||||||
|
|
||||||
static void ibx_write_infoframe(struct drm_encoder *encoder,
|
static void ibx_write_infoframe(struct drm_encoder *encoder,
|
||||||
enum hdmi_infoframe_type type,
|
enum hdmi_infoframe_type type,
|
||||||
const uint8_t *frame, ssize_t len)
|
const void *frame, ssize_t len)
|
||||||
{
|
{
|
||||||
uint32_t *data = (uint32_t *)frame;
|
const uint32_t *data = frame;
|
||||||
struct drm_device *dev = encoder->dev;
|
struct drm_device *dev = encoder->dev;
|
||||||
struct drm_i915_private *dev_priv = dev->dev_private;
|
struct drm_i915_private *dev_priv = dev->dev_private;
|
||||||
struct intel_crtc *intel_crtc = to_intel_crtc(encoder->crtc);
|
struct intel_crtc *intel_crtc = to_intel_crtc(encoder->crtc);
|
||||||
@@ -205,9 +205,9 @@ static void ibx_write_infoframe(struct drm_encoder *encoder,
|
|||||||
|
|
||||||
static void cpt_write_infoframe(struct drm_encoder *encoder,
|
static void cpt_write_infoframe(struct drm_encoder *encoder,
|
||||||
enum hdmi_infoframe_type type,
|
enum hdmi_infoframe_type type,
|
||||||
const uint8_t *frame, ssize_t len)
|
const void *frame, ssize_t len)
|
||||||
{
|
{
|
||||||
uint32_t *data = (uint32_t *)frame;
|
const uint32_t *data = frame;
|
||||||
struct drm_device *dev = encoder->dev;
|
struct drm_device *dev = encoder->dev;
|
||||||
struct drm_i915_private *dev_priv = dev->dev_private;
|
struct drm_i915_private *dev_priv = dev->dev_private;
|
||||||
struct intel_crtc *intel_crtc = to_intel_crtc(encoder->crtc);
|
struct intel_crtc *intel_crtc = to_intel_crtc(encoder->crtc);
|
||||||
@@ -246,9 +246,9 @@ static void cpt_write_infoframe(struct drm_encoder *encoder,
|
|||||||
|
|
||||||
static void vlv_write_infoframe(struct drm_encoder *encoder,
|
static void vlv_write_infoframe(struct drm_encoder *encoder,
|
||||||
enum hdmi_infoframe_type type,
|
enum hdmi_infoframe_type type,
|
||||||
const uint8_t *frame, ssize_t len)
|
const void *frame, ssize_t len)
|
||||||
{
|
{
|
||||||
uint32_t *data = (uint32_t *)frame;
|
const uint32_t *data = frame;
|
||||||
struct drm_device *dev = encoder->dev;
|
struct drm_device *dev = encoder->dev;
|
||||||
struct drm_i915_private *dev_priv = dev->dev_private;
|
struct drm_i915_private *dev_priv = dev->dev_private;
|
||||||
struct intel_crtc *intel_crtc = to_intel_crtc(encoder->crtc);
|
struct intel_crtc *intel_crtc = to_intel_crtc(encoder->crtc);
|
||||||
@@ -284,9 +284,9 @@ static void vlv_write_infoframe(struct drm_encoder *encoder,
|
|||||||
|
|
||||||
static void hsw_write_infoframe(struct drm_encoder *encoder,
|
static void hsw_write_infoframe(struct drm_encoder *encoder,
|
||||||
enum hdmi_infoframe_type type,
|
enum hdmi_infoframe_type type,
|
||||||
const uint8_t *frame, ssize_t len)
|
const void *frame, ssize_t len)
|
||||||
{
|
{
|
||||||
uint32_t *data = (uint32_t *)frame;
|
const uint32_t *data = frame;
|
||||||
struct drm_device *dev = encoder->dev;
|
struct drm_device *dev = encoder->dev;
|
||||||
struct drm_i915_private *dev_priv = dev->dev_private;
|
struct drm_i915_private *dev_priv = dev->dev_private;
|
||||||
struct intel_crtc *intel_crtc = to_intel_crtc(encoder->crtc);
|
struct intel_crtc *intel_crtc = to_intel_crtc(encoder->crtc);
|
||||||
|
@@ -447,9 +447,19 @@ static int intel_lid_notify(struct notifier_block *nb, unsigned long val,
|
|||||||
if (dev_priv->modeset_restore == MODESET_DONE)
|
if (dev_priv->modeset_restore == MODESET_DONE)
|
||||||
goto exit;
|
goto exit;
|
||||||
|
|
||||||
drm_modeset_lock_all(dev);
|
/*
|
||||||
intel_modeset_setup_hw_state(dev, true);
|
* Some old platform's BIOS love to wreak havoc while the lid is closed.
|
||||||
drm_modeset_unlock_all(dev);
|
* We try to detect this here and undo any damage. The split for PCH
|
||||||
|
* platforms is rather conservative and a bit arbitrary expect that on
|
||||||
|
* those platforms VGA disabling requires actual legacy VGA I/O access,
|
||||||
|
* and as part of the cleanup in the hw state restore we also redisable
|
||||||
|
* the vga plane.
|
||||||
|
*/
|
||||||
|
if (!HAS_PCH_SPLIT(dev)) {
|
||||||
|
drm_modeset_lock_all(dev);
|
||||||
|
intel_modeset_setup_hw_state(dev, true);
|
||||||
|
drm_modeset_unlock_all(dev);
|
||||||
|
}
|
||||||
|
|
||||||
dev_priv->modeset_restore = MODESET_DONE;
|
dev_priv->modeset_restore = MODESET_DONE;
|
||||||
|
|
||||||
@@ -745,57 +755,6 @@ static const struct dmi_system_id intel_no_lvds[] = {
|
|||||||
{ } /* terminating entry */
|
{ } /* terminating entry */
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
|
||||||
* intel_find_lvds_downclock - find the reduced downclock for LVDS in EDID
|
|
||||||
* @dev: drm device
|
|
||||||
* @connector: LVDS connector
|
|
||||||
*
|
|
||||||
* Find the reduced downclock for LVDS in EDID.
|
|
||||||
*/
|
|
||||||
static void intel_find_lvds_downclock(struct drm_device *dev,
|
|
||||||
struct drm_display_mode *fixed_mode,
|
|
||||||
struct drm_connector *connector)
|
|
||||||
{
|
|
||||||
struct drm_i915_private *dev_priv = dev->dev_private;
|
|
||||||
struct drm_display_mode *scan;
|
|
||||||
int temp_downclock;
|
|
||||||
|
|
||||||
temp_downclock = fixed_mode->clock;
|
|
||||||
list_for_each_entry(scan, &connector->probed_modes, head) {
|
|
||||||
/*
|
|
||||||
* If one mode has the same resolution with the fixed_panel
|
|
||||||
* mode while they have the different refresh rate, it means
|
|
||||||
* that the reduced downclock is found for the LVDS. In such
|
|
||||||
* case we can set the different FPx0/1 to dynamically select
|
|
||||||
* between low and high frequency.
|
|
||||||
*/
|
|
||||||
if (scan->hdisplay == fixed_mode->hdisplay &&
|
|
||||||
scan->hsync_start == fixed_mode->hsync_start &&
|
|
||||||
scan->hsync_end == fixed_mode->hsync_end &&
|
|
||||||
scan->htotal == fixed_mode->htotal &&
|
|
||||||
scan->vdisplay == fixed_mode->vdisplay &&
|
|
||||||
scan->vsync_start == fixed_mode->vsync_start &&
|
|
||||||
scan->vsync_end == fixed_mode->vsync_end &&
|
|
||||||
scan->vtotal == fixed_mode->vtotal) {
|
|
||||||
if (scan->clock < temp_downclock) {
|
|
||||||
/*
|
|
||||||
* The downclock is already found. But we
|
|
||||||
* expect to find the lower downclock.
|
|
||||||
*/
|
|
||||||
temp_downclock = scan->clock;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (temp_downclock < fixed_mode->clock && i915_lvds_downclock) {
|
|
||||||
/* We found the downclock for LVDS. */
|
|
||||||
dev_priv->lvds_downclock_avail = 1;
|
|
||||||
dev_priv->lvds_downclock = temp_downclock;
|
|
||||||
DRM_DEBUG_KMS("LVDS downclock is found in EDID. "
|
|
||||||
"Normal clock %dKhz, downclock %dKhz\n",
|
|
||||||
fixed_mode->clock, temp_downclock);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Enumerate the child dev array parsed from VBT to check whether
|
* Enumerate the child dev array parsed from VBT to check whether
|
||||||
* the LVDS is present.
|
* the LVDS is present.
|
||||||
@@ -1073,8 +1032,22 @@ void intel_lvds_init(struct drm_device *dev)
|
|||||||
|
|
||||||
fixed_mode = drm_mode_duplicate(dev, scan);
|
fixed_mode = drm_mode_duplicate(dev, scan);
|
||||||
if (fixed_mode) {
|
if (fixed_mode) {
|
||||||
intel_find_lvds_downclock(dev, fixed_mode,
|
intel_connector->panel.downclock_mode =
|
||||||
connector);
|
intel_find_panel_downclock(dev,
|
||||||
|
fixed_mode, connector);
|
||||||
|
if (intel_connector->panel.downclock_mode !=
|
||||||
|
NULL && i915_lvds_downclock) {
|
||||||
|
/* We found the downclock for LVDS. */
|
||||||
|
dev_priv->lvds_downclock_avail = true;
|
||||||
|
dev_priv->lvds_downclock =
|
||||||
|
intel_connector->panel.
|
||||||
|
downclock_mode->clock;
|
||||||
|
DRM_DEBUG_KMS("LVDS downclock is found"
|
||||||
|
" in EDID. Normal clock %dKhz, "
|
||||||
|
"downclock %dKhz\n",
|
||||||
|
fixed_mode->clock,
|
||||||
|
dev_priv->lvds_downclock);
|
||||||
|
}
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -64,7 +64,7 @@ struct opregion_header {
|
|||||||
u8 driver_ver[16];
|
u8 driver_ver[16];
|
||||||
u32 mboxes;
|
u32 mboxes;
|
||||||
u8 reserved[164];
|
u8 reserved[164];
|
||||||
} __attribute__((packed));
|
} __packed;
|
||||||
|
|
||||||
/* OpRegion mailbox #1: public ACPI methods */
|
/* OpRegion mailbox #1: public ACPI methods */
|
||||||
struct opregion_acpi {
|
struct opregion_acpi {
|
||||||
@@ -86,7 +86,7 @@ struct opregion_acpi {
|
|||||||
u32 cnot; /* current OS notification */
|
u32 cnot; /* current OS notification */
|
||||||
u32 nrdy; /* driver status */
|
u32 nrdy; /* driver status */
|
||||||
u8 rsvd2[60];
|
u8 rsvd2[60];
|
||||||
} __attribute__((packed));
|
} __packed;
|
||||||
|
|
||||||
/* OpRegion mailbox #2: SWSCI */
|
/* OpRegion mailbox #2: SWSCI */
|
||||||
struct opregion_swsci {
|
struct opregion_swsci {
|
||||||
@@ -94,7 +94,7 @@ struct opregion_swsci {
|
|||||||
u32 parm; /* command parameters */
|
u32 parm; /* command parameters */
|
||||||
u32 dslp; /* driver sleep time-out */
|
u32 dslp; /* driver sleep time-out */
|
||||||
u8 rsvd[244];
|
u8 rsvd[244];
|
||||||
} __attribute__((packed));
|
} __packed;
|
||||||
|
|
||||||
/* OpRegion mailbox #3: ASLE */
|
/* OpRegion mailbox #3: ASLE */
|
||||||
struct opregion_asle {
|
struct opregion_asle {
|
||||||
@@ -115,7 +115,7 @@ struct opregion_asle {
|
|||||||
u32 srot; /* supported rotation angles */
|
u32 srot; /* supported rotation angles */
|
||||||
u32 iuer; /* IUER events */
|
u32 iuer; /* IUER events */
|
||||||
u8 rsvd[86];
|
u8 rsvd[86];
|
||||||
} __attribute__((packed));
|
} __packed;
|
||||||
|
|
||||||
/* Driver readiness indicator */
|
/* Driver readiness indicator */
|
||||||
#define ASLE_ARDY_READY (1 << 0)
|
#define ASLE_ARDY_READY (1 << 0)
|
||||||
|
@@ -845,11 +845,14 @@ static int intel_backlight_device_get_brightness(struct backlight_device *bd)
|
|||||||
{
|
{
|
||||||
struct intel_connector *connector = bl_get_data(bd);
|
struct intel_connector *connector = bl_get_data(bd);
|
||||||
struct drm_device *dev = connector->base.dev;
|
struct drm_device *dev = connector->base.dev;
|
||||||
|
struct drm_i915_private *dev_priv = dev->dev_private;
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
|
intel_runtime_pm_get(dev_priv);
|
||||||
mutex_lock(&dev->mode_config.mutex);
|
mutex_lock(&dev->mode_config.mutex);
|
||||||
ret = intel_panel_get_backlight(connector);
|
ret = intel_panel_get_backlight(connector);
|
||||||
mutex_unlock(&dev->mode_config.mutex);
|
mutex_unlock(&dev->mode_config.mutex);
|
||||||
|
intel_runtime_pm_put(dev_priv);
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
@@ -1104,6 +1107,59 @@ void intel_panel_destroy_backlight(struct drm_connector *connector)
|
|||||||
intel_backlight_device_unregister(intel_connector);
|
intel_backlight_device_unregister(intel_connector);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* intel_find_panel_downclock - find the reduced downclock for LVDS in EDID
|
||||||
|
* @dev: drm device
|
||||||
|
* @fixed_mode : panel native mode
|
||||||
|
* @connector: LVDS/eDP connector
|
||||||
|
*
|
||||||
|
* Return downclock_avail
|
||||||
|
* Find the reduced downclock for LVDS/eDP in EDID.
|
||||||
|
*/
|
||||||
|
struct drm_display_mode *
|
||||||
|
intel_find_panel_downclock(struct drm_device *dev,
|
||||||
|
struct drm_display_mode *fixed_mode,
|
||||||
|
struct drm_connector *connector)
|
||||||
|
{
|
||||||
|
struct drm_display_mode *scan, *tmp_mode;
|
||||||
|
int temp_downclock;
|
||||||
|
|
||||||
|
temp_downclock = fixed_mode->clock;
|
||||||
|
tmp_mode = NULL;
|
||||||
|
|
||||||
|
list_for_each_entry(scan, &connector->probed_modes, head) {
|
||||||
|
/*
|
||||||
|
* If one mode has the same resolution with the fixed_panel
|
||||||
|
* mode while they have the different refresh rate, it means
|
||||||
|
* that the reduced downclock is found. In such
|
||||||
|
* case we can set the different FPx0/1 to dynamically select
|
||||||
|
* between low and high frequency.
|
||||||
|
*/
|
||||||
|
if (scan->hdisplay == fixed_mode->hdisplay &&
|
||||||
|
scan->hsync_start == fixed_mode->hsync_start &&
|
||||||
|
scan->hsync_end == fixed_mode->hsync_end &&
|
||||||
|
scan->htotal == fixed_mode->htotal &&
|
||||||
|
scan->vdisplay == fixed_mode->vdisplay &&
|
||||||
|
scan->vsync_start == fixed_mode->vsync_start &&
|
||||||
|
scan->vsync_end == fixed_mode->vsync_end &&
|
||||||
|
scan->vtotal == fixed_mode->vtotal) {
|
||||||
|
if (scan->clock < temp_downclock) {
|
||||||
|
/*
|
||||||
|
* The downclock is already found. But we
|
||||||
|
* expect to find the lower downclock.
|
||||||
|
*/
|
||||||
|
temp_downclock = scan->clock;
|
||||||
|
tmp_mode = scan;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (temp_downclock < fixed_mode->clock)
|
||||||
|
return drm_mode_duplicate(dev, tmp_mode);
|
||||||
|
else
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
/* Set up chip specific backlight functions */
|
/* Set up chip specific backlight functions */
|
||||||
void intel_panel_init_backlight_funcs(struct drm_device *dev)
|
void intel_panel_init_backlight_funcs(struct drm_device *dev)
|
||||||
{
|
{
|
||||||
@@ -1157,4 +1213,8 @@ void intel_panel_fini(struct intel_panel *panel)
|
|||||||
|
|
||||||
if (panel->fixed_mode)
|
if (panel->fixed_mode)
|
||||||
drm_mode_destroy(intel_connector->base.dev, panel->fixed_mode);
|
drm_mode_destroy(intel_connector->base.dev, panel->fixed_mode);
|
||||||
|
|
||||||
|
if (panel->downclock_mode)
|
||||||
|
drm_mode_destroy(intel_connector->base.dev,
|
||||||
|
panel->downclock_mode);
|
||||||
}
|
}
|
||||||
|
@@ -30,7 +30,9 @@
|
|||||||
#include "intel_drv.h"
|
#include "intel_drv.h"
|
||||||
#include "../../../platform/x86/intel_ips.h"
|
#include "../../../platform/x86/intel_ips.h"
|
||||||
#include <linux/module.h>
|
#include <linux/module.h>
|
||||||
|
#include <linux/vgaarb.h>
|
||||||
#include <drm/i915_powerwell.h>
|
#include <drm/i915_powerwell.h>
|
||||||
|
#include <linux/pm_runtime.h>
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* RC6 is a special power stage which allows the GPU to enter an very
|
* RC6 is a special power stage which allows the GPU to enter an very
|
||||||
@@ -86,7 +88,7 @@ static void i8xx_disable_fbc(struct drm_device *dev)
|
|||||||
DRM_DEBUG_KMS("disabled FBC\n");
|
DRM_DEBUG_KMS("disabled FBC\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
static void i8xx_enable_fbc(struct drm_crtc *crtc, unsigned long interval)
|
static void i8xx_enable_fbc(struct drm_crtc *crtc)
|
||||||
{
|
{
|
||||||
struct drm_device *dev = crtc->dev;
|
struct drm_device *dev = crtc->dev;
|
||||||
struct drm_i915_private *dev_priv = dev->dev_private;
|
struct drm_i915_private *dev_priv = dev->dev_private;
|
||||||
@@ -96,32 +98,40 @@ static void i8xx_enable_fbc(struct drm_crtc *crtc, unsigned long interval)
|
|||||||
struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
|
struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
|
||||||
int cfb_pitch;
|
int cfb_pitch;
|
||||||
int plane, i;
|
int plane, i;
|
||||||
u32 fbc_ctl, fbc_ctl2;
|
u32 fbc_ctl;
|
||||||
|
|
||||||
cfb_pitch = dev_priv->fbc.size / FBC_LL_SIZE;
|
cfb_pitch = dev_priv->fbc.size / FBC_LL_SIZE;
|
||||||
if (fb->pitches[0] < cfb_pitch)
|
if (fb->pitches[0] < cfb_pitch)
|
||||||
cfb_pitch = fb->pitches[0];
|
cfb_pitch = fb->pitches[0];
|
||||||
|
|
||||||
/* FBC_CTL wants 64B units */
|
/* FBC_CTL wants 32B or 64B units */
|
||||||
cfb_pitch = (cfb_pitch / 64) - 1;
|
if (IS_GEN2(dev))
|
||||||
|
cfb_pitch = (cfb_pitch / 32) - 1;
|
||||||
|
else
|
||||||
|
cfb_pitch = (cfb_pitch / 64) - 1;
|
||||||
plane = intel_crtc->plane == 0 ? FBC_CTL_PLANEA : FBC_CTL_PLANEB;
|
plane = intel_crtc->plane == 0 ? FBC_CTL_PLANEA : FBC_CTL_PLANEB;
|
||||||
|
|
||||||
/* Clear old tags */
|
/* Clear old tags */
|
||||||
for (i = 0; i < (FBC_LL_SIZE / 32) + 1; i++)
|
for (i = 0; i < (FBC_LL_SIZE / 32) + 1; i++)
|
||||||
I915_WRITE(FBC_TAG + (i * 4), 0);
|
I915_WRITE(FBC_TAG + (i * 4), 0);
|
||||||
|
|
||||||
/* Set it up... */
|
if (IS_GEN4(dev)) {
|
||||||
fbc_ctl2 = FBC_CTL_FENCE_DBL | FBC_CTL_IDLE_IMM | FBC_CTL_CPU_FENCE;
|
u32 fbc_ctl2;
|
||||||
fbc_ctl2 |= plane;
|
|
||||||
I915_WRITE(FBC_CONTROL2, fbc_ctl2);
|
/* Set it up... */
|
||||||
I915_WRITE(FBC_FENCE_OFF, crtc->y);
|
fbc_ctl2 = FBC_CTL_FENCE_DBL | FBC_CTL_IDLE_IMM | FBC_CTL_CPU_FENCE;
|
||||||
|
fbc_ctl2 |= plane;
|
||||||
|
I915_WRITE(FBC_CONTROL2, fbc_ctl2);
|
||||||
|
I915_WRITE(FBC_FENCE_OFF, crtc->y);
|
||||||
|
}
|
||||||
|
|
||||||
/* enable it... */
|
/* enable it... */
|
||||||
fbc_ctl = FBC_CTL_EN | FBC_CTL_PERIODIC;
|
fbc_ctl = I915_READ(FBC_CONTROL);
|
||||||
|
fbc_ctl &= 0x3fff << FBC_CTL_INTERVAL_SHIFT;
|
||||||
|
fbc_ctl |= FBC_CTL_EN | FBC_CTL_PERIODIC;
|
||||||
if (IS_I945GM(dev))
|
if (IS_I945GM(dev))
|
||||||
fbc_ctl |= FBC_CTL_C3_IDLE; /* 945 needs special SR handling */
|
fbc_ctl |= FBC_CTL_C3_IDLE; /* 945 needs special SR handling */
|
||||||
fbc_ctl |= (cfb_pitch & 0xff) << FBC_CTL_STRIDE_SHIFT;
|
fbc_ctl |= (cfb_pitch & 0xff) << FBC_CTL_STRIDE_SHIFT;
|
||||||
fbc_ctl |= (interval & 0x2fff) << FBC_CTL_INTERVAL_SHIFT;
|
|
||||||
fbc_ctl |= obj->fence_reg;
|
fbc_ctl |= obj->fence_reg;
|
||||||
I915_WRITE(FBC_CONTROL, fbc_ctl);
|
I915_WRITE(FBC_CONTROL, fbc_ctl);
|
||||||
|
|
||||||
@@ -136,7 +146,7 @@ static bool i8xx_fbc_enabled(struct drm_device *dev)
|
|||||||
return I915_READ(FBC_CONTROL) & FBC_CTL_EN;
|
return I915_READ(FBC_CONTROL) & FBC_CTL_EN;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void g4x_enable_fbc(struct drm_crtc *crtc, unsigned long interval)
|
static void g4x_enable_fbc(struct drm_crtc *crtc)
|
||||||
{
|
{
|
||||||
struct drm_device *dev = crtc->dev;
|
struct drm_device *dev = crtc->dev;
|
||||||
struct drm_i915_private *dev_priv = dev->dev_private;
|
struct drm_i915_private *dev_priv = dev->dev_private;
|
||||||
@@ -145,16 +155,12 @@ static void g4x_enable_fbc(struct drm_crtc *crtc, unsigned long interval)
|
|||||||
struct drm_i915_gem_object *obj = intel_fb->obj;
|
struct drm_i915_gem_object *obj = intel_fb->obj;
|
||||||
struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
|
struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
|
||||||
int plane = intel_crtc->plane == 0 ? DPFC_CTL_PLANEA : DPFC_CTL_PLANEB;
|
int plane = intel_crtc->plane == 0 ? DPFC_CTL_PLANEA : DPFC_CTL_PLANEB;
|
||||||
unsigned long stall_watermark = 200;
|
|
||||||
u32 dpfc_ctl;
|
u32 dpfc_ctl;
|
||||||
|
|
||||||
dpfc_ctl = plane | DPFC_SR_EN | DPFC_CTL_LIMIT_1X;
|
dpfc_ctl = plane | DPFC_SR_EN | DPFC_CTL_LIMIT_1X;
|
||||||
dpfc_ctl |= DPFC_CTL_FENCE_EN | obj->fence_reg;
|
dpfc_ctl |= DPFC_CTL_FENCE_EN | obj->fence_reg;
|
||||||
I915_WRITE(DPFC_CHICKEN, DPFC_HT_MODIFY);
|
I915_WRITE(DPFC_CHICKEN, DPFC_HT_MODIFY);
|
||||||
|
|
||||||
I915_WRITE(DPFC_RECOMP_CTL, DPFC_RECOMP_STALL_EN |
|
|
||||||
(stall_watermark << DPFC_RECOMP_STALL_WM_SHIFT) |
|
|
||||||
(interval << DPFC_RECOMP_TIMER_COUNT_SHIFT));
|
|
||||||
I915_WRITE(DPFC_FENCE_YOFF, crtc->y);
|
I915_WRITE(DPFC_FENCE_YOFF, crtc->y);
|
||||||
|
|
||||||
/* enable it... */
|
/* enable it... */
|
||||||
@@ -210,7 +216,7 @@ static void sandybridge_blit_fbc_update(struct drm_device *dev)
|
|||||||
gen6_gt_force_wake_put(dev_priv, FORCEWAKE_MEDIA);
|
gen6_gt_force_wake_put(dev_priv, FORCEWAKE_MEDIA);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void ironlake_enable_fbc(struct drm_crtc *crtc, unsigned long interval)
|
static void ironlake_enable_fbc(struct drm_crtc *crtc)
|
||||||
{
|
{
|
||||||
struct drm_device *dev = crtc->dev;
|
struct drm_device *dev = crtc->dev;
|
||||||
struct drm_i915_private *dev_priv = dev->dev_private;
|
struct drm_i915_private *dev_priv = dev->dev_private;
|
||||||
@@ -219,7 +225,6 @@ static void ironlake_enable_fbc(struct drm_crtc *crtc, unsigned long interval)
|
|||||||
struct drm_i915_gem_object *obj = intel_fb->obj;
|
struct drm_i915_gem_object *obj = intel_fb->obj;
|
||||||
struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
|
struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
|
||||||
int plane = intel_crtc->plane == 0 ? DPFC_CTL_PLANEA : DPFC_CTL_PLANEB;
|
int plane = intel_crtc->plane == 0 ? DPFC_CTL_PLANEA : DPFC_CTL_PLANEB;
|
||||||
unsigned long stall_watermark = 200;
|
|
||||||
u32 dpfc_ctl;
|
u32 dpfc_ctl;
|
||||||
|
|
||||||
dpfc_ctl = I915_READ(ILK_DPFC_CONTROL);
|
dpfc_ctl = I915_READ(ILK_DPFC_CONTROL);
|
||||||
@@ -232,9 +237,6 @@ static void ironlake_enable_fbc(struct drm_crtc *crtc, unsigned long interval)
|
|||||||
dpfc_ctl |= obj->fence_reg;
|
dpfc_ctl |= obj->fence_reg;
|
||||||
I915_WRITE(ILK_DPFC_CHICKEN, DPFC_HT_MODIFY);
|
I915_WRITE(ILK_DPFC_CHICKEN, DPFC_HT_MODIFY);
|
||||||
|
|
||||||
I915_WRITE(ILK_DPFC_RECOMP_CTL, DPFC_RECOMP_STALL_EN |
|
|
||||||
(stall_watermark << DPFC_RECOMP_STALL_WM_SHIFT) |
|
|
||||||
(interval << DPFC_RECOMP_TIMER_COUNT_SHIFT));
|
|
||||||
I915_WRITE(ILK_DPFC_FENCE_YOFF, crtc->y);
|
I915_WRITE(ILK_DPFC_FENCE_YOFF, crtc->y);
|
||||||
I915_WRITE(ILK_FBC_RT_BASE, i915_gem_obj_ggtt_offset(obj) | ILK_FBC_RT_VALID);
|
I915_WRITE(ILK_FBC_RT_BASE, i915_gem_obj_ggtt_offset(obj) | ILK_FBC_RT_VALID);
|
||||||
/* enable it... */
|
/* enable it... */
|
||||||
@@ -272,7 +274,7 @@ static bool ironlake_fbc_enabled(struct drm_device *dev)
|
|||||||
return I915_READ(ILK_DPFC_CONTROL) & DPFC_CTL_EN;
|
return I915_READ(ILK_DPFC_CONTROL) & DPFC_CTL_EN;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void gen7_enable_fbc(struct drm_crtc *crtc, unsigned long interval)
|
static void gen7_enable_fbc(struct drm_crtc *crtc)
|
||||||
{
|
{
|
||||||
struct drm_device *dev = crtc->dev;
|
struct drm_device *dev = crtc->dev;
|
||||||
struct drm_i915_private *dev_priv = dev->dev_private;
|
struct drm_i915_private *dev_priv = dev->dev_private;
|
||||||
@@ -329,8 +331,7 @@ static void intel_fbc_work_fn(struct work_struct *__work)
|
|||||||
* the prior work.
|
* the prior work.
|
||||||
*/
|
*/
|
||||||
if (work->crtc->fb == work->fb) {
|
if (work->crtc->fb == work->fb) {
|
||||||
dev_priv->display.enable_fbc(work->crtc,
|
dev_priv->display.enable_fbc(work->crtc);
|
||||||
work->interval);
|
|
||||||
|
|
||||||
dev_priv->fbc.plane = to_intel_crtc(work->crtc)->plane;
|
dev_priv->fbc.plane = to_intel_crtc(work->crtc)->plane;
|
||||||
dev_priv->fbc.fb_id = work->crtc->fb->base.id;
|
dev_priv->fbc.fb_id = work->crtc->fb->base.id;
|
||||||
@@ -367,7 +368,7 @@ static void intel_cancel_fbc_work(struct drm_i915_private *dev_priv)
|
|||||||
dev_priv->fbc.fbc_work = NULL;
|
dev_priv->fbc.fbc_work = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void intel_enable_fbc(struct drm_crtc *crtc, unsigned long interval)
|
static void intel_enable_fbc(struct drm_crtc *crtc)
|
||||||
{
|
{
|
||||||
struct intel_fbc_work *work;
|
struct intel_fbc_work *work;
|
||||||
struct drm_device *dev = crtc->dev;
|
struct drm_device *dev = crtc->dev;
|
||||||
@@ -381,13 +382,12 @@ static void intel_enable_fbc(struct drm_crtc *crtc, unsigned long interval)
|
|||||||
work = kzalloc(sizeof(*work), GFP_KERNEL);
|
work = kzalloc(sizeof(*work), GFP_KERNEL);
|
||||||
if (work == NULL) {
|
if (work == NULL) {
|
||||||
DRM_ERROR("Failed to allocate FBC work structure\n");
|
DRM_ERROR("Failed to allocate FBC work structure\n");
|
||||||
dev_priv->display.enable_fbc(crtc, interval);
|
dev_priv->display.enable_fbc(crtc);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
work->crtc = crtc;
|
work->crtc = crtc;
|
||||||
work->fb = crtc->fb;
|
work->fb = crtc->fb;
|
||||||
work->interval = interval;
|
|
||||||
INIT_DELAYED_WORK(&work->work, intel_fbc_work_fn);
|
INIT_DELAYED_WORK(&work->work, intel_fbc_work_fn);
|
||||||
|
|
||||||
dev_priv->fbc.fbc_work = work;
|
dev_priv->fbc.fbc_work = work;
|
||||||
@@ -537,10 +537,10 @@ void intel_update_fbc(struct drm_device *dev)
|
|||||||
DRM_DEBUG_KMS("mode too large for compression, disabling\n");
|
DRM_DEBUG_KMS("mode too large for compression, disabling\n");
|
||||||
goto out_disable;
|
goto out_disable;
|
||||||
}
|
}
|
||||||
if ((IS_I915GM(dev) || IS_I945GM(dev) || IS_HASWELL(dev)) &&
|
if ((INTEL_INFO(dev)->gen < 4 || IS_HASWELL(dev)) &&
|
||||||
intel_crtc->plane != 0) {
|
intel_crtc->plane != PLANE_A) {
|
||||||
if (set_no_fbc_reason(dev_priv, FBC_BAD_PLANE))
|
if (set_no_fbc_reason(dev_priv, FBC_BAD_PLANE))
|
||||||
DRM_DEBUG_KMS("plane not 0, disabling compression\n");
|
DRM_DEBUG_KMS("plane not A, disabling compression\n");
|
||||||
goto out_disable;
|
goto out_disable;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -602,7 +602,7 @@ void intel_update_fbc(struct drm_device *dev)
|
|||||||
intel_disable_fbc(dev);
|
intel_disable_fbc(dev);
|
||||||
}
|
}
|
||||||
|
|
||||||
intel_enable_fbc(crtc, 500);
|
intel_enable_fbc(crtc);
|
||||||
dev_priv->fbc.no_fbc_reason = FBC_OK;
|
dev_priv->fbc.no_fbc_reason = FBC_OK;
|
||||||
return;
|
return;
|
||||||
|
|
||||||
@@ -5257,19 +5257,33 @@ static void gen8_init_clock_gating(struct drm_device *dev)
|
|||||||
I915_WRITE(GEN7_HALF_SLICE_CHICKEN1,
|
I915_WRITE(GEN7_HALF_SLICE_CHICKEN1,
|
||||||
_MASKED_BIT_ENABLE(GEN7_SINGLE_SUBSCAN_DISPATCH_ENABLE));
|
_MASKED_BIT_ENABLE(GEN7_SINGLE_SUBSCAN_DISPATCH_ENABLE));
|
||||||
|
|
||||||
/* WaSwitchSolVfFArbitrationPriority */
|
/* WaSwitchSolVfFArbitrationPriority:bdw */
|
||||||
I915_WRITE(GAM_ECOCHK, I915_READ(GAM_ECOCHK) | HSW_ECOCHK_ARB_PRIO_SOL);
|
I915_WRITE(GAM_ECOCHK, I915_READ(GAM_ECOCHK) | HSW_ECOCHK_ARB_PRIO_SOL);
|
||||||
|
|
||||||
/* WaPsrDPAMaskVBlankInSRD */
|
/* WaPsrDPAMaskVBlankInSRD:bdw */
|
||||||
I915_WRITE(CHICKEN_PAR1_1,
|
I915_WRITE(CHICKEN_PAR1_1,
|
||||||
I915_READ(CHICKEN_PAR1_1) | DPA_MASK_VBLANK_SRD);
|
I915_READ(CHICKEN_PAR1_1) | DPA_MASK_VBLANK_SRD);
|
||||||
|
|
||||||
/* WaPsrDPRSUnmaskVBlankInSRD */
|
/* WaPsrDPRSUnmaskVBlankInSRD:bdw */
|
||||||
for_each_pipe(i) {
|
for_each_pipe(i) {
|
||||||
I915_WRITE(CHICKEN_PIPESL_1(i),
|
I915_WRITE(CHICKEN_PIPESL_1(i),
|
||||||
I915_READ(CHICKEN_PIPESL_1(i) |
|
I915_READ(CHICKEN_PIPESL_1(i) |
|
||||||
DPRS_MASK_VBLANK_SRD));
|
DPRS_MASK_VBLANK_SRD));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Use Force Non-Coherent whenever executing a 3D context. This is a
|
||||||
|
* workaround for for a possible hang in the unlikely event a TLB
|
||||||
|
* invalidation occurs during a PSD flush.
|
||||||
|
*/
|
||||||
|
I915_WRITE(HDC_CHICKEN0,
|
||||||
|
I915_READ(HDC_CHICKEN0) |
|
||||||
|
_MASKED_BIT_ENABLE(HDC_FORCE_NON_COHERENT));
|
||||||
|
|
||||||
|
/* WaVSRefCountFullforceMissDisable:bdw */
|
||||||
|
/* WaDSRefCountFullforceMissDisable:bdw */
|
||||||
|
I915_WRITE(GEN7_FF_THREAD_MODE,
|
||||||
|
I915_READ(GEN7_FF_THREAD_MODE) &
|
||||||
|
~(GEN8_FF_DS_REF_CNT_FFME | GEN7_FF_VS_REF_CNT_FFME));
|
||||||
}
|
}
|
||||||
|
|
||||||
static void haswell_init_clock_gating(struct drm_device *dev)
|
static void haswell_init_clock_gating(struct drm_device *dev)
|
||||||
@@ -5681,14 +5695,71 @@ bool intel_display_power_enabled(struct drm_device *dev,
|
|||||||
return is_enabled;
|
return is_enabled;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void hsw_power_well_post_enable(struct drm_i915_private *dev_priv)
|
||||||
|
{
|
||||||
|
struct drm_device *dev = dev_priv->dev;
|
||||||
|
unsigned long irqflags;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* After we re-enable the power well, if we touch VGA register 0x3d5
|
||||||
|
* we'll get unclaimed register interrupts. This stops after we write
|
||||||
|
* anything to the VGA MSR register. The vgacon module uses this
|
||||||
|
* register all the time, so if we unbind our driver and, as a
|
||||||
|
* consequence, bind vgacon, we'll get stuck in an infinite loop at
|
||||||
|
* console_unlock(). So make here we touch the VGA MSR register, making
|
||||||
|
* sure vgacon can keep working normally without triggering interrupts
|
||||||
|
* and error messages.
|
||||||
|
*/
|
||||||
|
vga_get_uninterruptible(dev->pdev, VGA_RSRC_LEGACY_IO);
|
||||||
|
outb(inb(VGA_MSR_READ), VGA_MSR_WRITE);
|
||||||
|
vga_put(dev->pdev, VGA_RSRC_LEGACY_IO);
|
||||||
|
|
||||||
|
if (IS_BROADWELL(dev)) {
|
||||||
|
spin_lock_irqsave(&dev_priv->irq_lock, irqflags);
|
||||||
|
I915_WRITE(GEN8_DE_PIPE_IMR(PIPE_B),
|
||||||
|
dev_priv->de_irq_mask[PIPE_B]);
|
||||||
|
I915_WRITE(GEN8_DE_PIPE_IER(PIPE_B),
|
||||||
|
~dev_priv->de_irq_mask[PIPE_B] |
|
||||||
|
GEN8_PIPE_VBLANK);
|
||||||
|
I915_WRITE(GEN8_DE_PIPE_IMR(PIPE_C),
|
||||||
|
dev_priv->de_irq_mask[PIPE_C]);
|
||||||
|
I915_WRITE(GEN8_DE_PIPE_IER(PIPE_C),
|
||||||
|
~dev_priv->de_irq_mask[PIPE_C] |
|
||||||
|
GEN8_PIPE_VBLANK);
|
||||||
|
POSTING_READ(GEN8_DE_PIPE_IER(PIPE_C));
|
||||||
|
spin_unlock_irqrestore(&dev_priv->irq_lock, irqflags);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void hsw_power_well_post_disable(struct drm_i915_private *dev_priv)
|
||||||
|
{
|
||||||
|
struct drm_device *dev = dev_priv->dev;
|
||||||
|
enum pipe p;
|
||||||
|
unsigned long irqflags;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* After this, the registers on the pipes that are part of the power
|
||||||
|
* well will become zero, so we have to adjust our counters according to
|
||||||
|
* that.
|
||||||
|
*
|
||||||
|
* FIXME: Should we do this in general in drm_vblank_post_modeset?
|
||||||
|
*/
|
||||||
|
spin_lock_irqsave(&dev->vbl_lock, irqflags);
|
||||||
|
for_each_pipe(p)
|
||||||
|
if (p != PIPE_A)
|
||||||
|
dev->vblank[p].last = 0;
|
||||||
|
spin_unlock_irqrestore(&dev->vbl_lock, irqflags);
|
||||||
|
}
|
||||||
|
|
||||||
static void hsw_set_power_well(struct drm_device *dev,
|
static void hsw_set_power_well(struct drm_device *dev,
|
||||||
struct i915_power_well *power_well, bool enable)
|
struct i915_power_well *power_well, bool enable)
|
||||||
{
|
{
|
||||||
struct drm_i915_private *dev_priv = dev->dev_private;
|
struct drm_i915_private *dev_priv = dev->dev_private;
|
||||||
bool is_enabled, enable_requested;
|
bool is_enabled, enable_requested;
|
||||||
unsigned long irqflags;
|
|
||||||
uint32_t tmp;
|
uint32_t tmp;
|
||||||
|
|
||||||
|
WARN_ON(dev_priv->pc8.enabled);
|
||||||
|
|
||||||
tmp = I915_READ(HSW_PWR_WELL_DRIVER);
|
tmp = I915_READ(HSW_PWR_WELL_DRIVER);
|
||||||
is_enabled = tmp & HSW_PWR_WELL_STATE_ENABLED;
|
is_enabled = tmp & HSW_PWR_WELL_STATE_ENABLED;
|
||||||
enable_requested = tmp & HSW_PWR_WELL_ENABLE_REQUEST;
|
enable_requested = tmp & HSW_PWR_WELL_ENABLE_REQUEST;
|
||||||
@@ -5705,42 +5776,14 @@ static void hsw_set_power_well(struct drm_device *dev,
|
|||||||
DRM_ERROR("Timeout enabling power well\n");
|
DRM_ERROR("Timeout enabling power well\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
if (IS_BROADWELL(dev)) {
|
hsw_power_well_post_enable(dev_priv);
|
||||||
spin_lock_irqsave(&dev_priv->irq_lock, irqflags);
|
|
||||||
I915_WRITE(GEN8_DE_PIPE_IMR(PIPE_B),
|
|
||||||
dev_priv->de_irq_mask[PIPE_B]);
|
|
||||||
I915_WRITE(GEN8_DE_PIPE_IER(PIPE_B),
|
|
||||||
~dev_priv->de_irq_mask[PIPE_B] |
|
|
||||||
GEN8_PIPE_VBLANK);
|
|
||||||
I915_WRITE(GEN8_DE_PIPE_IMR(PIPE_C),
|
|
||||||
dev_priv->de_irq_mask[PIPE_C]);
|
|
||||||
I915_WRITE(GEN8_DE_PIPE_IER(PIPE_C),
|
|
||||||
~dev_priv->de_irq_mask[PIPE_C] |
|
|
||||||
GEN8_PIPE_VBLANK);
|
|
||||||
POSTING_READ(GEN8_DE_PIPE_IER(PIPE_C));
|
|
||||||
spin_unlock_irqrestore(&dev_priv->irq_lock, irqflags);
|
|
||||||
}
|
|
||||||
} else {
|
} else {
|
||||||
if (enable_requested) {
|
if (enable_requested) {
|
||||||
enum pipe p;
|
|
||||||
|
|
||||||
I915_WRITE(HSW_PWR_WELL_DRIVER, 0);
|
I915_WRITE(HSW_PWR_WELL_DRIVER, 0);
|
||||||
POSTING_READ(HSW_PWR_WELL_DRIVER);
|
POSTING_READ(HSW_PWR_WELL_DRIVER);
|
||||||
DRM_DEBUG_KMS("Requesting to disable the power well\n");
|
DRM_DEBUG_KMS("Requesting to disable the power well\n");
|
||||||
|
|
||||||
/*
|
hsw_power_well_post_disable(dev_priv);
|
||||||
* After this, the registers on the pipes that are part
|
|
||||||
* of the power well will become zero, so we have to
|
|
||||||
* adjust our counters according to that.
|
|
||||||
*
|
|
||||||
* FIXME: Should we do this in general in
|
|
||||||
* drm_vblank_post_modeset?
|
|
||||||
*/
|
|
||||||
spin_lock_irqsave(&dev->vbl_lock, irqflags);
|
|
||||||
for_each_pipe(p)
|
|
||||||
if (p != PIPE_A)
|
|
||||||
dev->vblank[p].last = 0;
|
|
||||||
spin_unlock_irqrestore(&dev->vbl_lock, irqflags);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -5748,17 +5791,26 @@ static void hsw_set_power_well(struct drm_device *dev,
|
|||||||
static void __intel_power_well_get(struct drm_device *dev,
|
static void __intel_power_well_get(struct drm_device *dev,
|
||||||
struct i915_power_well *power_well)
|
struct i915_power_well *power_well)
|
||||||
{
|
{
|
||||||
if (!power_well->count++ && power_well->set)
|
struct drm_i915_private *dev_priv = dev->dev_private;
|
||||||
|
|
||||||
|
if (!power_well->count++ && power_well->set) {
|
||||||
|
hsw_disable_package_c8(dev_priv);
|
||||||
power_well->set(dev, power_well, true);
|
power_well->set(dev, power_well, true);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void __intel_power_well_put(struct drm_device *dev,
|
static void __intel_power_well_put(struct drm_device *dev,
|
||||||
struct i915_power_well *power_well)
|
struct i915_power_well *power_well)
|
||||||
{
|
{
|
||||||
|
struct drm_i915_private *dev_priv = dev->dev_private;
|
||||||
|
|
||||||
WARN_ON(!power_well->count);
|
WARN_ON(!power_well->count);
|
||||||
|
|
||||||
if (!--power_well->count && power_well->set && i915_disable_power_well)
|
if (!--power_well->count && power_well->set &&
|
||||||
|
i915_disable_power_well) {
|
||||||
power_well->set(dev, power_well, false);
|
power_well->set(dev, power_well, false);
|
||||||
|
hsw_enable_package_c8(dev_priv);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void intel_display_power_get(struct drm_device *dev,
|
void intel_display_power_get(struct drm_device *dev,
|
||||||
@@ -5951,31 +6003,86 @@ void intel_aux_display_runtime_put(struct drm_i915_private *dev_priv)
|
|||||||
hsw_enable_package_c8(dev_priv);
|
hsw_enable_package_c8(dev_priv);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void intel_runtime_pm_get(struct drm_i915_private *dev_priv)
|
||||||
|
{
|
||||||
|
struct drm_device *dev = dev_priv->dev;
|
||||||
|
struct device *device = &dev->pdev->dev;
|
||||||
|
|
||||||
|
if (!HAS_RUNTIME_PM(dev))
|
||||||
|
return;
|
||||||
|
|
||||||
|
pm_runtime_get_sync(device);
|
||||||
|
WARN(dev_priv->pm.suspended, "Device still suspended.\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
void intel_runtime_pm_put(struct drm_i915_private *dev_priv)
|
||||||
|
{
|
||||||
|
struct drm_device *dev = dev_priv->dev;
|
||||||
|
struct device *device = &dev->pdev->dev;
|
||||||
|
|
||||||
|
if (!HAS_RUNTIME_PM(dev))
|
||||||
|
return;
|
||||||
|
|
||||||
|
pm_runtime_mark_last_busy(device);
|
||||||
|
pm_runtime_put_autosuspend(device);
|
||||||
|
}
|
||||||
|
|
||||||
|
void intel_init_runtime_pm(struct drm_i915_private *dev_priv)
|
||||||
|
{
|
||||||
|
struct drm_device *dev = dev_priv->dev;
|
||||||
|
struct device *device = &dev->pdev->dev;
|
||||||
|
|
||||||
|
dev_priv->pm.suspended = false;
|
||||||
|
|
||||||
|
if (!HAS_RUNTIME_PM(dev))
|
||||||
|
return;
|
||||||
|
|
||||||
|
pm_runtime_set_active(device);
|
||||||
|
|
||||||
|
pm_runtime_set_autosuspend_delay(device, 10000); /* 10s */
|
||||||
|
pm_runtime_mark_last_busy(device);
|
||||||
|
pm_runtime_use_autosuspend(device);
|
||||||
|
}
|
||||||
|
|
||||||
|
void intel_fini_runtime_pm(struct drm_i915_private *dev_priv)
|
||||||
|
{
|
||||||
|
struct drm_device *dev = dev_priv->dev;
|
||||||
|
struct device *device = &dev->pdev->dev;
|
||||||
|
|
||||||
|
if (!HAS_RUNTIME_PM(dev))
|
||||||
|
return;
|
||||||
|
|
||||||
|
/* Make sure we're not suspended first. */
|
||||||
|
pm_runtime_get_sync(device);
|
||||||
|
pm_runtime_disable(device);
|
||||||
|
}
|
||||||
|
|
||||||
/* Set up chip specific power management-related functions */
|
/* Set up chip specific power management-related functions */
|
||||||
void intel_init_pm(struct drm_device *dev)
|
void intel_init_pm(struct drm_device *dev)
|
||||||
{
|
{
|
||||||
struct drm_i915_private *dev_priv = dev->dev_private;
|
struct drm_i915_private *dev_priv = dev->dev_private;
|
||||||
|
|
||||||
if (I915_HAS_FBC(dev)) {
|
if (I915_HAS_FBC(dev)) {
|
||||||
if (HAS_PCH_SPLIT(dev)) {
|
if (INTEL_INFO(dev)->gen >= 7) {
|
||||||
dev_priv->display.fbc_enabled = ironlake_fbc_enabled;
|
dev_priv->display.fbc_enabled = ironlake_fbc_enabled;
|
||||||
if (IS_IVYBRIDGE(dev) || IS_HASWELL(dev))
|
dev_priv->display.enable_fbc = gen7_enable_fbc;
|
||||||
dev_priv->display.enable_fbc =
|
dev_priv->display.disable_fbc = ironlake_disable_fbc;
|
||||||
gen7_enable_fbc;
|
} else if (INTEL_INFO(dev)->gen >= 5) {
|
||||||
else
|
dev_priv->display.fbc_enabled = ironlake_fbc_enabled;
|
||||||
dev_priv->display.enable_fbc =
|
dev_priv->display.enable_fbc = ironlake_enable_fbc;
|
||||||
ironlake_enable_fbc;
|
|
||||||
dev_priv->display.disable_fbc = ironlake_disable_fbc;
|
dev_priv->display.disable_fbc = ironlake_disable_fbc;
|
||||||
} else if (IS_GM45(dev)) {
|
} else if (IS_GM45(dev)) {
|
||||||
dev_priv->display.fbc_enabled = g4x_fbc_enabled;
|
dev_priv->display.fbc_enabled = g4x_fbc_enabled;
|
||||||
dev_priv->display.enable_fbc = g4x_enable_fbc;
|
dev_priv->display.enable_fbc = g4x_enable_fbc;
|
||||||
dev_priv->display.disable_fbc = g4x_disable_fbc;
|
dev_priv->display.disable_fbc = g4x_disable_fbc;
|
||||||
} else if (IS_CRESTLINE(dev)) {
|
} else {
|
||||||
dev_priv->display.fbc_enabled = i8xx_fbc_enabled;
|
dev_priv->display.fbc_enabled = i8xx_fbc_enabled;
|
||||||
dev_priv->display.enable_fbc = i8xx_enable_fbc;
|
dev_priv->display.enable_fbc = i8xx_enable_fbc;
|
||||||
dev_priv->display.disable_fbc = i8xx_disable_fbc;
|
dev_priv->display.disable_fbc = i8xx_disable_fbc;
|
||||||
|
|
||||||
|
/* This value was pulled out of someone's hat */
|
||||||
|
I915_WRITE(FBC_CONTROL, 500 << FBC_CTL_INTERVAL_SHIFT);
|
||||||
}
|
}
|
||||||
/* 855GM needs testing */
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* For cxsr */
|
/* For cxsr */
|
||||||
|
@@ -952,7 +952,7 @@ static void intel_sdvo_dump_hdmi_buf(struct intel_sdvo *intel_sdvo)
|
|||||||
|
|
||||||
static bool intel_sdvo_write_infoframe(struct intel_sdvo *intel_sdvo,
|
static bool intel_sdvo_write_infoframe(struct intel_sdvo *intel_sdvo,
|
||||||
unsigned if_index, uint8_t tx_rate,
|
unsigned if_index, uint8_t tx_rate,
|
||||||
uint8_t *data, unsigned length)
|
const uint8_t *data, unsigned length)
|
||||||
{
|
{
|
||||||
uint8_t set_buf_index[2] = { if_index, 0 };
|
uint8_t set_buf_index[2] = { if_index, 0 };
|
||||||
uint8_t hbuf_size, tmp[8];
|
uint8_t hbuf_size, tmp[8];
|
||||||
|
@@ -59,7 +59,7 @@ struct intel_sdvo_caps {
|
|||||||
unsigned int stall_support:1;
|
unsigned int stall_support:1;
|
||||||
unsigned int pad:1;
|
unsigned int pad:1;
|
||||||
u16 output_flags;
|
u16 output_flags;
|
||||||
} __attribute__((packed));
|
} __packed;
|
||||||
|
|
||||||
/* Note: SDVO detailed timing flags match EDID misc flags. */
|
/* Note: SDVO detailed timing flags match EDID misc flags. */
|
||||||
#define DTD_FLAG_HSYNC_POSITIVE (1 << 1)
|
#define DTD_FLAG_HSYNC_POSITIVE (1 << 1)
|
||||||
@@ -94,12 +94,12 @@ struct intel_sdvo_dtd {
|
|||||||
u8 v_sync_off_high;
|
u8 v_sync_off_high;
|
||||||
u8 reserved;
|
u8 reserved;
|
||||||
} part2;
|
} part2;
|
||||||
} __attribute__((packed));
|
} __packed;
|
||||||
|
|
||||||
struct intel_sdvo_pixel_clock_range {
|
struct intel_sdvo_pixel_clock_range {
|
||||||
u16 min; /**< pixel clock, in 10kHz units */
|
u16 min; /**< pixel clock, in 10kHz units */
|
||||||
u16 max; /**< pixel clock, in 10kHz units */
|
u16 max; /**< pixel clock, in 10kHz units */
|
||||||
} __attribute__((packed));
|
} __packed;
|
||||||
|
|
||||||
struct intel_sdvo_preferred_input_timing_args {
|
struct intel_sdvo_preferred_input_timing_args {
|
||||||
u16 clock;
|
u16 clock;
|
||||||
@@ -108,7 +108,7 @@ struct intel_sdvo_preferred_input_timing_args {
|
|||||||
u8 interlace:1;
|
u8 interlace:1;
|
||||||
u8 scaled:1;
|
u8 scaled:1;
|
||||||
u8 pad:6;
|
u8 pad:6;
|
||||||
} __attribute__((packed));
|
} __packed;
|
||||||
|
|
||||||
/* I2C registers for SDVO */
|
/* I2C registers for SDVO */
|
||||||
#define SDVO_I2C_ARG_0 0x07
|
#define SDVO_I2C_ARG_0 0x07
|
||||||
@@ -162,7 +162,7 @@ struct intel_sdvo_get_trained_inputs_response {
|
|||||||
unsigned int input0_trained:1;
|
unsigned int input0_trained:1;
|
||||||
unsigned int input1_trained:1;
|
unsigned int input1_trained:1;
|
||||||
unsigned int pad:6;
|
unsigned int pad:6;
|
||||||
} __attribute__((packed));
|
} __packed;
|
||||||
|
|
||||||
/** Returns a struct intel_sdvo_output_flags of active outputs. */
|
/** Returns a struct intel_sdvo_output_flags of active outputs. */
|
||||||
#define SDVO_CMD_GET_ACTIVE_OUTPUTS 0x04
|
#define SDVO_CMD_GET_ACTIVE_OUTPUTS 0x04
|
||||||
@@ -219,7 +219,7 @@ struct intel_sdvo_get_interrupt_event_source_response {
|
|||||||
unsigned int ambient_light_interrupt:1;
|
unsigned int ambient_light_interrupt:1;
|
||||||
unsigned int hdmi_audio_encrypt_change:1;
|
unsigned int hdmi_audio_encrypt_change:1;
|
||||||
unsigned int pad:6;
|
unsigned int pad:6;
|
||||||
} __attribute__((packed));
|
} __packed;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Selects which input is affected by future input commands.
|
* Selects which input is affected by future input commands.
|
||||||
@@ -232,7 +232,7 @@ struct intel_sdvo_get_interrupt_event_source_response {
|
|||||||
struct intel_sdvo_set_target_input_args {
|
struct intel_sdvo_set_target_input_args {
|
||||||
unsigned int target_1:1;
|
unsigned int target_1:1;
|
||||||
unsigned int pad:7;
|
unsigned int pad:7;
|
||||||
} __attribute__((packed));
|
} __packed;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Takes a struct intel_sdvo_output_flags of which outputs are targeted by
|
* Takes a struct intel_sdvo_output_flags of which outputs are targeted by
|
||||||
@@ -370,7 +370,7 @@ struct intel_sdvo_tv_format {
|
|||||||
unsigned int hdtv_std_eia_7702a_480i_60:1;
|
unsigned int hdtv_std_eia_7702a_480i_60:1;
|
||||||
unsigned int hdtv_std_eia_7702a_480p_60:1;
|
unsigned int hdtv_std_eia_7702a_480p_60:1;
|
||||||
unsigned int pad:3;
|
unsigned int pad:3;
|
||||||
} __attribute__((packed));
|
} __packed;
|
||||||
|
|
||||||
#define SDVO_CMD_GET_TV_FORMAT 0x28
|
#define SDVO_CMD_GET_TV_FORMAT 0x28
|
||||||
|
|
||||||
@@ -401,7 +401,7 @@ struct intel_sdvo_sdtv_resolution_request {
|
|||||||
unsigned int secam_l:1;
|
unsigned int secam_l:1;
|
||||||
unsigned int secam_60:1;
|
unsigned int secam_60:1;
|
||||||
unsigned int pad:5;
|
unsigned int pad:5;
|
||||||
} __attribute__((packed));
|
} __packed;
|
||||||
|
|
||||||
struct intel_sdvo_sdtv_resolution_reply {
|
struct intel_sdvo_sdtv_resolution_reply {
|
||||||
unsigned int res_320x200:1;
|
unsigned int res_320x200:1;
|
||||||
@@ -426,7 +426,7 @@ struct intel_sdvo_sdtv_resolution_reply {
|
|||||||
unsigned int res_1024x768:1;
|
unsigned int res_1024x768:1;
|
||||||
unsigned int res_1280x1024:1;
|
unsigned int res_1280x1024:1;
|
||||||
unsigned int pad:5;
|
unsigned int pad:5;
|
||||||
} __attribute__((packed));
|
} __packed;
|
||||||
|
|
||||||
/* Get supported resolution with squire pixel aspect ratio that can be
|
/* Get supported resolution with squire pixel aspect ratio that can be
|
||||||
scaled for the requested HDTV format */
|
scaled for the requested HDTV format */
|
||||||
@@ -463,7 +463,7 @@ struct intel_sdvo_hdtv_resolution_request {
|
|||||||
unsigned int hdtv_std_eia_7702a_480i_60:1;
|
unsigned int hdtv_std_eia_7702a_480i_60:1;
|
||||||
unsigned int hdtv_std_eia_7702a_480p_60:1;
|
unsigned int hdtv_std_eia_7702a_480p_60:1;
|
||||||
unsigned int pad:6;
|
unsigned int pad:6;
|
||||||
} __attribute__((packed));
|
} __packed;
|
||||||
|
|
||||||
struct intel_sdvo_hdtv_resolution_reply {
|
struct intel_sdvo_hdtv_resolution_reply {
|
||||||
unsigned int res_640x480:1;
|
unsigned int res_640x480:1;
|
||||||
@@ -517,7 +517,7 @@ struct intel_sdvo_hdtv_resolution_reply {
|
|||||||
|
|
||||||
unsigned int res_1280x768:1;
|
unsigned int res_1280x768:1;
|
||||||
unsigned int pad5:7;
|
unsigned int pad5:7;
|
||||||
} __attribute__((packed));
|
} __packed;
|
||||||
|
|
||||||
/* Get supported power state returns info for encoder and monitor, rely on
|
/* Get supported power state returns info for encoder and monitor, rely on
|
||||||
last SetTargetInput and SetTargetOutput calls */
|
last SetTargetInput and SetTargetOutput calls */
|
||||||
@@ -557,13 +557,13 @@ struct sdvo_panel_power_sequencing {
|
|||||||
|
|
||||||
unsigned int t4_high:2;
|
unsigned int t4_high:2;
|
||||||
unsigned int pad:6;
|
unsigned int pad:6;
|
||||||
} __attribute__((packed));
|
} __packed;
|
||||||
|
|
||||||
#define SDVO_CMD_GET_MAX_BACKLIGHT_LEVEL 0x30
|
#define SDVO_CMD_GET_MAX_BACKLIGHT_LEVEL 0x30
|
||||||
struct sdvo_max_backlight_reply {
|
struct sdvo_max_backlight_reply {
|
||||||
u8 max_value;
|
u8 max_value;
|
||||||
u8 default_value;
|
u8 default_value;
|
||||||
} __attribute__((packed));
|
} __packed;
|
||||||
|
|
||||||
#define SDVO_CMD_GET_BACKLIGHT_LEVEL 0x31
|
#define SDVO_CMD_GET_BACKLIGHT_LEVEL 0x31
|
||||||
#define SDVO_CMD_SET_BACKLIGHT_LEVEL 0x32
|
#define SDVO_CMD_SET_BACKLIGHT_LEVEL 0x32
|
||||||
@@ -573,14 +573,14 @@ struct sdvo_get_ambient_light_reply {
|
|||||||
u16 trip_low;
|
u16 trip_low;
|
||||||
u16 trip_high;
|
u16 trip_high;
|
||||||
u16 value;
|
u16 value;
|
||||||
} __attribute__((packed));
|
} __packed;
|
||||||
#define SDVO_CMD_SET_AMBIENT_LIGHT 0x34
|
#define SDVO_CMD_SET_AMBIENT_LIGHT 0x34
|
||||||
struct sdvo_set_ambient_light_reply {
|
struct sdvo_set_ambient_light_reply {
|
||||||
u16 trip_low;
|
u16 trip_low;
|
||||||
u16 trip_high;
|
u16 trip_high;
|
||||||
unsigned int enable:1;
|
unsigned int enable:1;
|
||||||
unsigned int pad:7;
|
unsigned int pad:7;
|
||||||
} __attribute__((packed));
|
} __packed;
|
||||||
|
|
||||||
/* Set display power state */
|
/* Set display power state */
|
||||||
#define SDVO_CMD_SET_DISPLAY_POWER_STATE 0x7d
|
#define SDVO_CMD_SET_DISPLAY_POWER_STATE 0x7d
|
||||||
@@ -608,7 +608,7 @@ struct intel_sdvo_enhancements_reply {
|
|||||||
unsigned int dither:1;
|
unsigned int dither:1;
|
||||||
unsigned int tv_chroma_filter:1;
|
unsigned int tv_chroma_filter:1;
|
||||||
unsigned int tv_luma_filter:1;
|
unsigned int tv_luma_filter:1;
|
||||||
} __attribute__((packed));
|
} __packed;
|
||||||
|
|
||||||
/* Picture enhancement limits below are dependent on the current TV format,
|
/* Picture enhancement limits below are dependent on the current TV format,
|
||||||
* and thus need to be queried and set after it.
|
* and thus need to be queried and set after it.
|
||||||
@@ -630,7 +630,7 @@ struct intel_sdvo_enhancements_reply {
|
|||||||
struct intel_sdvo_enhancement_limits_reply {
|
struct intel_sdvo_enhancement_limits_reply {
|
||||||
u16 max_value;
|
u16 max_value;
|
||||||
u16 default_value;
|
u16 default_value;
|
||||||
} __attribute__((packed));
|
} __packed;
|
||||||
|
|
||||||
#define SDVO_CMD_GET_LVDS_PANEL_INFORMATION 0x7f
|
#define SDVO_CMD_GET_LVDS_PANEL_INFORMATION 0x7f
|
||||||
#define SDVO_CMD_SET_LVDS_PANEL_INFORMATION 0x80
|
#define SDVO_CMD_SET_LVDS_PANEL_INFORMATION 0x80
|
||||||
@@ -671,7 +671,7 @@ struct intel_sdvo_enhancement_limits_reply {
|
|||||||
#define SDVO_CMD_SET_TV_LUMA_FILTER 0x79
|
#define SDVO_CMD_SET_TV_LUMA_FILTER 0x79
|
||||||
struct intel_sdvo_enhancements_arg {
|
struct intel_sdvo_enhancements_arg {
|
||||||
u16 value;
|
u16 value;
|
||||||
} __attribute__((packed));
|
} __packed;
|
||||||
|
|
||||||
#define SDVO_CMD_GET_DOT_CRAWL 0x70
|
#define SDVO_CMD_GET_DOT_CRAWL 0x70
|
||||||
#define SDVO_CMD_SET_DOT_CRAWL 0x71
|
#define SDVO_CMD_SET_DOT_CRAWL 0x71
|
||||||
@@ -727,4 +727,4 @@ struct intel_sdvo_enhancements_arg {
|
|||||||
struct intel_sdvo_encode {
|
struct intel_sdvo_encode {
|
||||||
u8 dvi_rev;
|
u8 dvi_rev;
|
||||||
u8 hdmi_rev;
|
u8 hdmi_rev;
|
||||||
} __attribute__ ((packed));
|
} __packed;
|
||||||
|
@@ -249,3 +249,17 @@ void intel_sbi_write(struct drm_i915_private *dev_priv, u16 reg, u32 value,
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
u32 vlv_flisdsi_read(struct drm_i915_private *dev_priv, u32 reg)
|
||||||
|
{
|
||||||
|
u32 val = 0;
|
||||||
|
vlv_sideband_rw(dev_priv, DPIO_DEVFN, IOSF_PORT_FLISDSI,
|
||||||
|
DPIO_OPCODE_REG_READ, reg, &val);
|
||||||
|
return val;
|
||||||
|
}
|
||||||
|
|
||||||
|
void vlv_flisdsi_write(struct drm_i915_private *dev_priv, u32 reg, u32 val)
|
||||||
|
{
|
||||||
|
vlv_sideband_rw(dev_priv, DPIO_DEVFN, IOSF_PORT_FLISDSI,
|
||||||
|
DPIO_OPCODE_REG_WRITE, reg, &val);
|
||||||
|
}
|
||||||
|
@@ -150,6 +150,13 @@ static int __gen6_gt_wait_for_fifo(struct drm_i915_private *dev_priv)
|
|||||||
{
|
{
|
||||||
int ret = 0;
|
int ret = 0;
|
||||||
|
|
||||||
|
/* On VLV, FIFO will be shared by both SW and HW.
|
||||||
|
* So, we need to read the FREE_ENTRIES everytime */
|
||||||
|
if (IS_VALLEYVIEW(dev_priv->dev))
|
||||||
|
dev_priv->uncore.fifo_count =
|
||||||
|
__raw_i915_read32(dev_priv, GTFIFOCTL) &
|
||||||
|
GT_FIFO_FREE_ENTRIES_MASK;
|
||||||
|
|
||||||
if (dev_priv->uncore.fifo_count < GT_FIFO_NUM_RESERVED_ENTRIES) {
|
if (dev_priv->uncore.fifo_count < GT_FIFO_NUM_RESERVED_ENTRIES) {
|
||||||
int loop = 500;
|
int loop = 500;
|
||||||
u32 fifo = __raw_i915_read32(dev_priv, GTFIFOCTL) & GT_FIFO_FREE_ENTRIES_MASK;
|
u32 fifo = __raw_i915_read32(dev_priv, GTFIFOCTL) & GT_FIFO_FREE_ENTRIES_MASK;
|
||||||
@@ -325,6 +332,11 @@ void intel_uncore_early_sanitize(struct drm_device *dev)
|
|||||||
DRM_INFO("Found %zuMB of eLLC\n", dev_priv->ellc_size);
|
DRM_INFO("Found %zuMB of eLLC\n", dev_priv->ellc_size);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* clear out old GT FIFO errors */
|
||||||
|
if (IS_GEN6(dev) || IS_GEN7(dev))
|
||||||
|
__raw_i915_write32(dev_priv, GTFIFODBG,
|
||||||
|
__raw_i915_read32(dev_priv, GTFIFODBG));
|
||||||
|
|
||||||
intel_uncore_forcewake_reset(dev);
|
intel_uncore_forcewake_reset(dev);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -333,8 +345,6 @@ void intel_uncore_sanitize(struct drm_device *dev)
|
|||||||
struct drm_i915_private *dev_priv = dev->dev_private;
|
struct drm_i915_private *dev_priv = dev->dev_private;
|
||||||
u32 reg_val;
|
u32 reg_val;
|
||||||
|
|
||||||
intel_uncore_forcewake_reset(dev);
|
|
||||||
|
|
||||||
/* BIOS often leaves RC6 enabled, but disable it for hw init */
|
/* BIOS often leaves RC6 enabled, but disable it for hw init */
|
||||||
intel_disable_gt_powersave(dev);
|
intel_disable_gt_powersave(dev);
|
||||||
|
|
||||||
@@ -365,6 +375,8 @@ void gen6_gt_force_wake_get(struct drm_i915_private *dev_priv, int fw_engine)
|
|||||||
if (!dev_priv->uncore.funcs.force_wake_get)
|
if (!dev_priv->uncore.funcs.force_wake_get)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
intel_runtime_pm_get(dev_priv);
|
||||||
|
|
||||||
/* Redirect to VLV specific routine */
|
/* Redirect to VLV specific routine */
|
||||||
if (IS_VALLEYVIEW(dev_priv->dev))
|
if (IS_VALLEYVIEW(dev_priv->dev))
|
||||||
return vlv_force_wake_get(dev_priv, fw_engine);
|
return vlv_force_wake_get(dev_priv, fw_engine);
|
||||||
@@ -398,6 +410,8 @@ void gen6_gt_force_wake_put(struct drm_i915_private *dev_priv, int fw_engine)
|
|||||||
1);
|
1);
|
||||||
}
|
}
|
||||||
spin_unlock_irqrestore(&dev_priv->uncore.lock, irqflags);
|
spin_unlock_irqrestore(&dev_priv->uncore.lock, irqflags);
|
||||||
|
|
||||||
|
intel_runtime_pm_put(dev_priv);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* We give fast paths for the really cool registers */
|
/* We give fast paths for the really cool registers */
|
||||||
@@ -432,6 +446,13 @@ hsw_unclaimed_reg_check(struct drm_i915_private *dev_priv, u32 reg)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
assert_device_not_suspended(struct drm_i915_private *dev_priv)
|
||||||
|
{
|
||||||
|
WARN(HAS_RUNTIME_PM(dev_priv->dev) && dev_priv->pm.suspended,
|
||||||
|
"Device suspended\n");
|
||||||
|
}
|
||||||
|
|
||||||
#define REG_READ_HEADER(x) \
|
#define REG_READ_HEADER(x) \
|
||||||
unsigned long irqflags; \
|
unsigned long irqflags; \
|
||||||
u##x val = 0; \
|
u##x val = 0; \
|
||||||
@@ -535,12 +556,15 @@ __gen4_read(64)
|
|||||||
trace_i915_reg_rw(true, reg, val, sizeof(val), trace); \
|
trace_i915_reg_rw(true, reg, val, sizeof(val), trace); \
|
||||||
spin_lock_irqsave(&dev_priv->uncore.lock, irqflags)
|
spin_lock_irqsave(&dev_priv->uncore.lock, irqflags)
|
||||||
|
|
||||||
|
#define REG_WRITE_FOOTER \
|
||||||
|
spin_unlock_irqrestore(&dev_priv->uncore.lock, irqflags)
|
||||||
|
|
||||||
#define __gen4_write(x) \
|
#define __gen4_write(x) \
|
||||||
static void \
|
static void \
|
||||||
gen4_write##x(struct drm_i915_private *dev_priv, off_t reg, u##x val, bool trace) { \
|
gen4_write##x(struct drm_i915_private *dev_priv, off_t reg, u##x val, bool trace) { \
|
||||||
REG_WRITE_HEADER; \
|
REG_WRITE_HEADER; \
|
||||||
__raw_i915_write##x(dev_priv, reg, val); \
|
__raw_i915_write##x(dev_priv, reg, val); \
|
||||||
spin_unlock_irqrestore(&dev_priv->uncore.lock, irqflags); \
|
REG_WRITE_FOOTER; \
|
||||||
}
|
}
|
||||||
|
|
||||||
#define __gen5_write(x) \
|
#define __gen5_write(x) \
|
||||||
@@ -549,7 +573,7 @@ gen5_write##x(struct drm_i915_private *dev_priv, off_t reg, u##x val, bool trace
|
|||||||
REG_WRITE_HEADER; \
|
REG_WRITE_HEADER; \
|
||||||
ilk_dummy_write(dev_priv); \
|
ilk_dummy_write(dev_priv); \
|
||||||
__raw_i915_write##x(dev_priv, reg, val); \
|
__raw_i915_write##x(dev_priv, reg, val); \
|
||||||
spin_unlock_irqrestore(&dev_priv->uncore.lock, irqflags); \
|
REG_WRITE_FOOTER; \
|
||||||
}
|
}
|
||||||
|
|
||||||
#define __gen6_write(x) \
|
#define __gen6_write(x) \
|
||||||
@@ -560,11 +584,12 @@ gen6_write##x(struct drm_i915_private *dev_priv, off_t reg, u##x val, bool trace
|
|||||||
if (NEEDS_FORCE_WAKE((dev_priv), (reg))) { \
|
if (NEEDS_FORCE_WAKE((dev_priv), (reg))) { \
|
||||||
__fifo_ret = __gen6_gt_wait_for_fifo(dev_priv); \
|
__fifo_ret = __gen6_gt_wait_for_fifo(dev_priv); \
|
||||||
} \
|
} \
|
||||||
|
assert_device_not_suspended(dev_priv); \
|
||||||
__raw_i915_write##x(dev_priv, reg, val); \
|
__raw_i915_write##x(dev_priv, reg, val); \
|
||||||
if (unlikely(__fifo_ret)) { \
|
if (unlikely(__fifo_ret)) { \
|
||||||
gen6_gt_check_fifodbg(dev_priv); \
|
gen6_gt_check_fifodbg(dev_priv); \
|
||||||
} \
|
} \
|
||||||
spin_unlock_irqrestore(&dev_priv->uncore.lock, irqflags); \
|
REG_WRITE_FOOTER; \
|
||||||
}
|
}
|
||||||
|
|
||||||
#define __hsw_write(x) \
|
#define __hsw_write(x) \
|
||||||
@@ -575,13 +600,14 @@ hsw_write##x(struct drm_i915_private *dev_priv, off_t reg, u##x val, bool trace)
|
|||||||
if (NEEDS_FORCE_WAKE((dev_priv), (reg))) { \
|
if (NEEDS_FORCE_WAKE((dev_priv), (reg))) { \
|
||||||
__fifo_ret = __gen6_gt_wait_for_fifo(dev_priv); \
|
__fifo_ret = __gen6_gt_wait_for_fifo(dev_priv); \
|
||||||
} \
|
} \
|
||||||
|
assert_device_not_suspended(dev_priv); \
|
||||||
hsw_unclaimed_reg_clear(dev_priv, reg); \
|
hsw_unclaimed_reg_clear(dev_priv, reg); \
|
||||||
__raw_i915_write##x(dev_priv, reg, val); \
|
__raw_i915_write##x(dev_priv, reg, val); \
|
||||||
if (unlikely(__fifo_ret)) { \
|
if (unlikely(__fifo_ret)) { \
|
||||||
gen6_gt_check_fifodbg(dev_priv); \
|
gen6_gt_check_fifodbg(dev_priv); \
|
||||||
} \
|
} \
|
||||||
hsw_unclaimed_reg_check(dev_priv, reg); \
|
hsw_unclaimed_reg_check(dev_priv, reg); \
|
||||||
spin_unlock_irqrestore(&dev_priv->uncore.lock, irqflags); \
|
REG_WRITE_FOOTER; \
|
||||||
}
|
}
|
||||||
|
|
||||||
static const u32 gen8_shadowed_regs[] = {
|
static const u32 gen8_shadowed_regs[] = {
|
||||||
@@ -608,7 +634,7 @@ static bool is_gen8_shadowed(struct drm_i915_private *dev_priv, u32 reg)
|
|||||||
#define __gen8_write(x) \
|
#define __gen8_write(x) \
|
||||||
static void \
|
static void \
|
||||||
gen8_write##x(struct drm_i915_private *dev_priv, off_t reg, u##x val, bool trace) { \
|
gen8_write##x(struct drm_i915_private *dev_priv, off_t reg, u##x val, bool trace) { \
|
||||||
bool __needs_put = !is_gen8_shadowed(dev_priv, reg); \
|
bool __needs_put = reg < 0x40000 && !is_gen8_shadowed(dev_priv, reg); \
|
||||||
REG_WRITE_HEADER; \
|
REG_WRITE_HEADER; \
|
||||||
if (__needs_put) { \
|
if (__needs_put) { \
|
||||||
dev_priv->uncore.funcs.force_wake_get(dev_priv, \
|
dev_priv->uncore.funcs.force_wake_get(dev_priv, \
|
||||||
@@ -619,7 +645,7 @@ gen8_write##x(struct drm_i915_private *dev_priv, off_t reg, u##x val, bool trace
|
|||||||
dev_priv->uncore.funcs.force_wake_put(dev_priv, \
|
dev_priv->uncore.funcs.force_wake_put(dev_priv, \
|
||||||
FORCEWAKE_ALL); \
|
FORCEWAKE_ALL); \
|
||||||
} \
|
} \
|
||||||
spin_unlock_irqrestore(&dev_priv->uncore.lock, irqflags); \
|
REG_WRITE_FOOTER; \
|
||||||
}
|
}
|
||||||
|
|
||||||
__gen8_write(8)
|
__gen8_write(8)
|
||||||
@@ -648,6 +674,7 @@ __gen4_write(64)
|
|||||||
#undef __gen6_write
|
#undef __gen6_write
|
||||||
#undef __gen5_write
|
#undef __gen5_write
|
||||||
#undef __gen4_write
|
#undef __gen4_write
|
||||||
|
#undef REG_WRITE_FOOTER
|
||||||
#undef REG_WRITE_HEADER
|
#undef REG_WRITE_HEADER
|
||||||
|
|
||||||
void intel_uncore_init(struct drm_device *dev)
|
void intel_uncore_init(struct drm_device *dev)
|
||||||
|
Reference in New Issue
Block a user