mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git
synced 2024-09-30 14:19:16 +00:00
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:
commit
859ae233cd
28 changed files with 947 additions and 506 deletions
|
@ -564,10 +564,12 @@ static int i915_gem_seqno_info(struct seq_file *m, void *data)
|
|||
ret = mutex_lock_interruptible(&dev->struct_mutex);
|
||||
if (ret)
|
||||
return ret;
|
||||
intel_runtime_pm_get(dev_priv);
|
||||
|
||||
for_each_ring(ring, dev_priv, i)
|
||||
i915_ring_seqno_info(m, ring);
|
||||
|
||||
intel_runtime_pm_put(dev_priv);
|
||||
mutex_unlock(&dev->struct_mutex);
|
||||
|
||||
return 0;
|
||||
|
@ -585,6 +587,7 @@ static int i915_interrupt_info(struct seq_file *m, void *data)
|
|||
ret = mutex_lock_interruptible(&dev->struct_mutex);
|
||||
if (ret)
|
||||
return ret;
|
||||
intel_runtime_pm_get(dev_priv);
|
||||
|
||||
if (INTEL_INFO(dev)->gen >= 8) {
|
||||
int i;
|
||||
|
@ -711,6 +714,7 @@ static int i915_interrupt_info(struct seq_file *m, void *data)
|
|||
}
|
||||
i915_ring_seqno_info(m, ring);
|
||||
}
|
||||
intel_runtime_pm_put(dev_priv);
|
||||
mutex_unlock(&dev->struct_mutex);
|
||||
|
||||
return 0;
|
||||
|
@ -904,9 +908,11 @@ static int i915_rstdby_delays(struct seq_file *m, void *unused)
|
|||
ret = mutex_lock_interruptible(&dev->struct_mutex);
|
||||
if (ret)
|
||||
return ret;
|
||||
intel_runtime_pm_get(dev_priv);
|
||||
|
||||
crstanddelay = I915_READ16(CRSTANDVID);
|
||||
|
||||
intel_runtime_pm_put(dev_priv);
|
||||
mutex_unlock(&dev->struct_mutex);
|
||||
|
||||
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_device *dev = node->minor->dev;
|
||||
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);
|
||||
|
||||
|
@ -945,7 +953,7 @@ static int i915_cur_delayinfo(struct seq_file *m, void *unused)
|
|||
/* RPSTAT1 is in the GT power well */
|
||||
ret = mutex_lock_interruptible(&dev->struct_mutex);
|
||||
if (ret)
|
||||
return ret;
|
||||
goto out;
|
||||
|
||||
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");
|
||||
}
|
||||
|
||||
return 0;
|
||||
out:
|
||||
intel_runtime_pm_put(dev_priv);
|
||||
return ret;
|
||||
}
|
||||
|
||||
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);
|
||||
if (ret)
|
||||
return ret;
|
||||
intel_runtime_pm_get(dev_priv);
|
||||
|
||||
for (i = 0; i < 16; i++) {
|
||||
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);
|
||||
}
|
||||
|
||||
intel_runtime_pm_put(dev_priv);
|
||||
|
||||
mutex_unlock(&dev->struct_mutex);
|
||||
|
||||
return 0;
|
||||
|
@ -1075,12 +1088,14 @@ static int i915_inttoext_table(struct seq_file *m, void *unused)
|
|||
ret = mutex_lock_interruptible(&dev->struct_mutex);
|
||||
if (ret)
|
||||
return ret;
|
||||
intel_runtime_pm_get(dev_priv);
|
||||
|
||||
for (i = 1; i <= 32; i++) {
|
||||
inttoext = I915_READ(INTTOEXT_BASE_ILK + i * 4);
|
||||
seq_printf(m, "INTTOEXT%02d: 0x%08x\n", i, inttoext);
|
||||
}
|
||||
|
||||
intel_runtime_pm_put(dev_priv);
|
||||
mutex_unlock(&dev->struct_mutex);
|
||||
|
||||
return 0;
|
||||
|
@ -1098,11 +1113,13 @@ static int ironlake_drpc_info(struct seq_file *m)
|
|||
ret = mutex_lock_interruptible(&dev->struct_mutex);
|
||||
if (ret)
|
||||
return ret;
|
||||
intel_runtime_pm_get(dev_priv);
|
||||
|
||||
rgvmodectl = I915_READ(MEMMODECTL);
|
||||
rstdbyctl = I915_READ(RSTDBYCTL);
|
||||
crstandvid = I915_READ16(CRSTANDVID);
|
||||
|
||||
intel_runtime_pm_put(dev_priv);
|
||||
mutex_unlock(&dev->struct_mutex);
|
||||
|
||||
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);
|
||||
if (ret)
|
||||
return ret;
|
||||
intel_runtime_pm_get(dev_priv);
|
||||
|
||||
spin_lock_irq(&dev_priv->uncore.lock);
|
||||
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);
|
||||
mutex_unlock(&dev_priv->rps.hw_lock);
|
||||
|
||||
intel_runtime_pm_put(dev_priv);
|
||||
|
||||
seq_printf(m, "Video Turbo Mode: %s\n",
|
||||
yesno(rpmodectl1 & GEN6_RP_MEDIA_TURBO));
|
||||
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);
|
||||
if (ret)
|
||||
return ret;
|
||||
intel_runtime_pm_get(dev_priv);
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
intel_runtime_pm_put(dev_priv);
|
||||
mutex_unlock(&dev_priv->rps.hw_lock);
|
||||
|
||||
return 0;
|
||||
|
@ -1436,8 +1458,10 @@ static int i915_gfxec(struct seq_file *m, void *unused)
|
|||
ret = mutex_lock_interruptible(&dev->struct_mutex);
|
||||
if (ret)
|
||||
return ret;
|
||||
intel_runtime_pm_get(dev_priv);
|
||||
|
||||
seq_printf(m, "GFXEC: %ld\n", (unsigned long)I915_READ(0x112f4));
|
||||
intel_runtime_pm_put(dev_priv);
|
||||
|
||||
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);
|
||||
if (ret)
|
||||
return ret;
|
||||
intel_runtime_pm_get(dev_priv);
|
||||
|
||||
seq_printf(m, "bit6 swizzle for X-tiling = %s\n",
|
||||
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",
|
||||
I915_READ(DISP_ARB_CTL));
|
||||
}
|
||||
intel_runtime_pm_put(dev_priv);
|
||||
mutex_unlock(&dev->struct_mutex);
|
||||
|
||||
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_device *dev = node->minor->dev;
|
||||
struct drm_i915_private *dev_priv = dev->dev_private;
|
||||
|
||||
int ret = mutex_lock_interruptible(&dev->struct_mutex);
|
||||
if (ret)
|
||||
return ret;
|
||||
intel_runtime_pm_get(dev_priv);
|
||||
|
||||
if (INTEL_INFO(dev)->gen >= 8)
|
||||
gen8_ppgtt_info(m, dev);
|
||||
else if (INTEL_INFO(dev)->gen >= 6)
|
||||
gen6_ppgtt_info(m, dev);
|
||||
|
||||
intel_runtime_pm_put(dev_priv);
|
||||
mutex_unlock(&dev->struct_mutex);
|
||||
|
||||
return 0;
|
||||
|
@ -1791,6 +1820,8 @@ static int i915_edp_psr_status(struct seq_file *m, void *data)
|
|||
u32 psrperf = 0;
|
||||
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, "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;
|
||||
seq_printf(m, "Performance_Counter: %u\n", psrperf);
|
||||
|
||||
intel_runtime_pm_put(dev_priv);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -3016,8 +3048,11 @@ i915_cache_sharing_get(void *data, u64 *val)
|
|||
ret = mutex_lock_interruptible(&dev->struct_mutex);
|
||||
if (ret)
|
||||
return ret;
|
||||
intel_runtime_pm_get(dev_priv);
|
||||
|
||||
snpcr = I915_READ(GEN6_MBCUNIT_SNPCR);
|
||||
|
||||
intel_runtime_pm_put(dev_priv);
|
||||
mutex_unlock(&dev_priv->dev->struct_mutex);
|
||||
|
||||
*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)
|
||||
return -EINVAL;
|
||||
|
||||
intel_runtime_pm_get(dev_priv);
|
||||
DRM_DEBUG_DRIVER("Manually setting uncore sharing to %llu\n", val);
|
||||
|
||||
/* 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);
|
||||
I915_WRITE(GEN6_MBCUNIT_SNPCR, snpcr);
|
||||
|
||||
intel_runtime_pm_put(dev_priv);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -3061,6 +3098,7 @@ static int i915_forcewake_open(struct inode *inode, struct file *file)
|
|||
if (INTEL_INFO(dev)->gen < 6)
|
||||
return 0;
|
||||
|
||||
intel_runtime_pm_get(dev_priv);
|
||||
gen6_gt_force_wake_get(dev_priv, FORCEWAKE_ALL);
|
||||
|
||||
return 0;
|
||||
|
@ -3075,6 +3113,7 @@ static int i915_forcewake_release(struct inode *inode, struct file *file)
|
|||
return 0;
|
||||
|
||||
gen6_gt_force_wake_put(dev_priv, FORCEWAKE_ALL);
|
||||
intel_runtime_pm_put(dev_priv);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
|
@ -42,6 +42,8 @@
|
|||
#include <linux/vga_switcheroo.h>
|
||||
#include <linux/slab.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])
|
||||
|
||||
|
@ -1667,6 +1669,8 @@ int i915_driver_load(struct drm_device *dev, unsigned long flags)
|
|||
if (IS_GEN5(dev))
|
||||
intel_gpu_ips_init(dev_priv);
|
||||
|
||||
intel_init_runtime_pm(dev_priv);
|
||||
|
||||
return 0;
|
||||
|
||||
out_power_well:
|
||||
|
@ -1706,6 +1710,14 @@ int i915_driver_unload(struct drm_device *dev)
|
|||
struct drm_i915_private *dev_priv = dev->dev_private;
|
||||
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();
|
||||
|
||||
/* 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)
|
||||
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);
|
||||
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,
|
||||
.cursor_needs_physical = 1,
|
||||
.has_overlay = 1, .overlay_needs_physical = 1,
|
||||
.has_fbc = 1,
|
||||
.ring_mask = RENDER_RING,
|
||||
};
|
||||
|
||||
|
@ -191,6 +192,7 @@ static const struct intel_device_info intel_i915gm_info = {
|
|||
.cursor_needs_physical = 1,
|
||||
.has_overlay = 1, .overlay_needs_physical = 1,
|
||||
.supports_tv = 1,
|
||||
.has_fbc = 1,
|
||||
.ring_mask = RENDER_RING,
|
||||
};
|
||||
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_overlay = 1, .overlay_needs_physical = 1,
|
||||
.supports_tv = 1,
|
||||
.has_fbc = 1,
|
||||
.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_crtc *crtc;
|
||||
|
||||
intel_runtime_pm_get(dev_priv);
|
||||
|
||||
/* ignore lid events during suspend */
|
||||
mutex_lock(&dev_priv->modeset_restore_lock);
|
||||
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);
|
||||
dev_priv->modeset_restore = MODESET_DONE;
|
||||
mutex_unlock(&dev_priv->modeset_restore_lock);
|
||||
|
||||
intel_runtime_pm_put(dev_priv);
|
||||
return error;
|
||||
}
|
||||
|
||||
|
@ -902,6 +909,38 @@ static int i915_pm_poweroff(struct device *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 = {
|
||||
.suspend = i915_pm_suspend,
|
||||
.resume = i915_pm_resume,
|
||||
|
@ -909,6 +948,8 @@ static const struct dev_pm_ops i915_pm_ops = {
|
|||
.thaw = i915_pm_thaw,
|
||||
.poweroff = i915_pm_poweroff,
|
||||
.restore = i915_pm_resume,
|
||||
.runtime_suspend = i915_runtime_suspend,
|
||||
.runtime_resume = i915_runtime_resume,
|
||||
};
|
||||
|
||||
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 extra_instdone[I915_NUM_INSTDONE_REG];
|
||||
u32 seqno[I915_NUM_RINGS];
|
||||
u64 bbaddr;
|
||||
u64 bbaddr[I915_NUM_RINGS];
|
||||
u32 fault_reg[I915_NUM_RINGS];
|
||||
u32 done_reg;
|
||||
u32 faddr[I915_NUM_RINGS];
|
||||
|
@ -372,7 +372,7 @@ struct dpll;
|
|||
|
||||
struct drm_i915_display_funcs {
|
||||
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);
|
||||
int (*get_display_clock_speed)(struct drm_device *dev);
|
||||
int (*get_fifo_size)(struct drm_device *dev, int plane);
|
||||
|
@ -695,7 +695,6 @@ struct i915_fbc {
|
|||
struct delayed_work work;
|
||||
struct drm_crtc *crtc;
|
||||
struct drm_framebuffer *fb;
|
||||
int interval;
|
||||
} *fbc_work;
|
||||
|
||||
enum no_fbc_reason {
|
||||
|
@ -1289,6 +1288,10 @@ struct i915_package_c8 {
|
|||
} regsave;
|
||||
};
|
||||
|
||||
struct i915_runtime_pm {
|
||||
bool suspended;
|
||||
};
|
||||
|
||||
enum intel_pipe_crc_source {
|
||||
INTEL_PIPE_CRC_SOURCE_NONE,
|
||||
INTEL_PIPE_CRC_SOURCE_PLANE1,
|
||||
|
@ -1519,6 +1522,8 @@ typedef struct drm_i915_private {
|
|||
|
||||
struct i915_package_c8 pc8;
|
||||
|
||||
struct i915_runtime_pm pm;
|
||||
|
||||
/* Old dri1 support infrastructure, beware the dragons ya fools entering
|
||||
* here! */
|
||||
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_PSR(dev) (IS_HASWELL(dev) || IS_BROADWELL(dev))
|
||||
#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_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);
|
||||
void intel_sbi_write(struct drm_i915_private *dev_priv, u16 reg, u32 value,
|
||||
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_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)
|
||||
{
|
||||
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;
|
||||
DEFINE_WAIT(wait);
|
||||
long timeout_jiffies;
|
||||
unsigned long timeout_expire;
|
||||
int ret;
|
||||
|
||||
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))
|
||||
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)) {
|
||||
gen6_rps_boost(dev_priv);
|
||||
|
@ -1035,8 +1037,7 @@ static int __wait_seqno(struct intel_ring_buffer *ring, u32 seqno,
|
|||
msecs_to_jiffies(100));
|
||||
}
|
||||
|
||||
if (!(dev_priv->gpu_error.test_irq_rings & intel_ring_flag(ring)) &&
|
||||
WARN_ON(!ring->irq_get(ring)))
|
||||
if (!irq_test_in_progress && WARN_ON(!ring->irq_get(ring)))
|
||||
return -ENODEV;
|
||||
|
||||
/* 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);
|
||||
for (;;) {
|
||||
struct timer_list timer;
|
||||
unsigned long expire;
|
||||
|
||||
prepare_to_wait(&ring->irq_queue, &wait,
|
||||
interruptible ? TASK_INTERRUPTIBLE : TASK_UNINTERRUPTIBLE);
|
||||
|
@ -1070,23 +1070,22 @@ static int __wait_seqno(struct intel_ring_buffer *ring, u32 seqno,
|
|||
break;
|
||||
}
|
||||
|
||||
if (timeout_jiffies <= 0) {
|
||||
if (timeout && time_after_eq(jiffies, timeout_expire)) {
|
||||
ret = -ETIME;
|
||||
break;
|
||||
}
|
||||
|
||||
timer.function = NULL;
|
||||
if (timeout || missed_irq(dev_priv, ring)) {
|
||||
unsigned long expire;
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
io_schedule();
|
||||
|
||||
if (timeout)
|
||||
timeout_jiffies = expire - jiffies;
|
||||
|
||||
if (timer.function) {
|
||||
del_singleshot_timer_sync(&timer);
|
||||
destroy_timer_on_stack(&timer);
|
||||
|
@ -1095,7 +1094,8 @@ static int __wait_seqno(struct intel_ring_buffer *ring, u32 seqno,
|
|||
getrawmonotonic(&now);
|
||||
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);
|
||||
|
||||
|
@ -1380,6 +1380,8 @@ int i915_gem_fault(struct vm_area_struct *vma, struct vm_fault *vmf)
|
|||
int ret = 0;
|
||||
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 */
|
||||
page_offset = ((unsigned long)vmf->virtual_address - vma->vm_start) >>
|
||||
PAGE_SHIFT;
|
||||
|
@ -1427,8 +1429,10 @@ int i915_gem_fault(struct vm_area_struct *vma, struct vm_fault *vmf)
|
|||
/* If this -EIO is due to a gpu hang, give the reset code a
|
||||
* chance to clean up the mess. Otherwise return the proper
|
||||
* SIGBUS. */
|
||||
if (i915_terminally_wedged(&dev_priv->gpu_error))
|
||||
return VM_FAULT_SIGBUS;
|
||||
if (i915_terminally_wedged(&dev_priv->gpu_error)) {
|
||||
ret = VM_FAULT_SIGBUS;
|
||||
break;
|
||||
}
|
||||
case -EAGAIN:
|
||||
/*
|
||||
* EAGAIN means the gpu is hung and we'll wait for the error
|
||||
|
@ -1443,15 +1447,22 @@ int i915_gem_fault(struct vm_area_struct *vma, struct vm_fault *vmf)
|
|||
* EBUSY is ok: this just means that another thread
|
||||
* already did the job.
|
||||
*/
|
||||
return VM_FAULT_NOPAGE;
|
||||
ret = VM_FAULT_NOPAGE;
|
||||
break;
|
||||
case -ENOMEM:
|
||||
return VM_FAULT_OOM;
|
||||
ret = VM_FAULT_OOM;
|
||||
break;
|
||||
case -ENOSPC:
|
||||
return VM_FAULT_SIGBUS;
|
||||
ret = VM_FAULT_SIGBUS;
|
||||
break;
|
||||
default:
|
||||
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;
|
||||
}
|
||||
i915_gem_gtt_finish_object(obj);
|
||||
i915_gem_object_unpin_pages(obj);
|
||||
|
||||
list_del(&vma->mm_list);
|
||||
/* 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;
|
||||
|
||||
drm_mm_remove_node(&vma->node);
|
||||
|
||||
i915_gem_vma_destroy(vma);
|
||||
|
||||
/* 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))
|
||||
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;
|
||||
}
|
||||
|
||||
|
@ -4165,6 +4180,8 @@ void i915_gem_free_object(struct drm_gem_object *gem_obj)
|
|||
drm_i915_private_t *dev_priv = dev->dev_private;
|
||||
struct i915_vma *vma, *next;
|
||||
|
||||
intel_runtime_pm_get(dev_priv);
|
||||
|
||||
trace_i915_gem_object_destroy(obj);
|
||||
|
||||
if (obj->phys_obj)
|
||||
|
@ -4209,6 +4226,8 @@ void i915_gem_free_object(struct drm_gem_object *gem_obj)
|
|||
|
||||
kfree(obj->bit_17);
|
||||
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,
|
||||
|
|
|
@ -888,6 +888,24 @@ validate_exec_list(struct drm_i915_gem_exec_object2 *exec,
|
|||
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
|
||||
i915_gem_execbuffer_move_to_active(struct list_head *vmas,
|
||||
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_clip_rect *cliprects = NULL;
|
||||
struct intel_ring_buffer *ring;
|
||||
struct i915_ctx_hang_stats *hs;
|
||||
u32 ctx_id = i915_execbuffer2_get_context_id(*args);
|
||||
const u32 ctx_id = i915_execbuffer2_get_context_id(*args);
|
||||
u32 exec_start, exec_len;
|
||||
u32 mask, flags;
|
||||
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);
|
||||
if (ret)
|
||||
goto pre_mutex_err;
|
||||
|
@ -1105,6 +1124,12 @@ i915_gem_do_execbuffer(struct drm_device *dev, void *data,
|
|||
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);
|
||||
if (eb == NULL) {
|
||||
mutex_unlock(&dev->struct_mutex);
|
||||
|
@ -1157,17 +1182,6 @@ i915_gem_do_execbuffer(struct drm_device *dev, void *data,
|
|||
if (ret)
|
||||
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);
|
||||
if (ret)
|
||||
goto err;
|
||||
|
@ -1229,6 +1243,10 @@ i915_gem_do_execbuffer(struct drm_device *dev, void *data,
|
|||
|
||||
pre_mutex_err:
|
||||
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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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, " IPEHR: 0x%08x\n", error->ipehr[ring]);
|
||||
err_printf(m, " INSTDONE: 0x%08x\n", error->instdone[ring]);
|
||||
if (ring == RCS && INTEL_INFO(dev)->gen >= 4)
|
||||
err_printf(m, " BBADDR: 0x%08llx\n", error->bbaddr);
|
||||
if (INTEL_INFO(dev)->gen >= 4)
|
||||
if (INTEL_INFO(dev)->gen >= 4) {
|
||||
err_printf(m, " BBADDR: 0x%08llx\n", error->bbaddr[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, " INSTPM: 0x%08x\n", error->instpm[ring]);
|
||||
err_printf(m, " FADDR: 0x%08x\n", error->faddr[ring]);
|
||||
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->instdone[ring->id] = I915_READ(RING_INSTDONE(ring->mmio_base));
|
||||
error->instps[ring->id] = I915_READ(RING_INSTPS(ring->mmio_base));
|
||||
if (ring->id == RCS)
|
||||
error->bbaddr = I915_READ64(BB_ADDR);
|
||||
error->bbaddr[ring->id] = I915_READ(RING_BBADDR(ring->mmio_base));
|
||||
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));
|
||||
} else {
|
||||
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.
|
||||
*/
|
||||
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;
|
||||
u16 flip_pending = DISPLAY_PLANE_FLIP_PENDING(pipe);
|
||||
u16 flip_pending = DISPLAY_PLANE_FLIP_PENDING(plane);
|
||||
|
||||
if (!drm_handle_vblank(dev, pipe))
|
||||
return false;
|
||||
|
@ -3150,7 +3150,7 @@ static bool i8xx_handle_vblank(struct drm_device *dev,
|
|||
if ((iir & flip_pending) == 0)
|
||||
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'
|
||||
* 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]);
|
||||
|
||||
for_each_pipe(pipe) {
|
||||
int plane = pipe;
|
||||
if (IS_MOBILE(dev))
|
||||
plane = !plane;
|
||||
|
||||
if (pipe_stats[pipe] & PIPE_VBLANK_INTERRUPT_STATUS &&
|
||||
i8xx_handle_vblank(dev, pipe, iir))
|
||||
flip_mask &= ~DISPLAY_PLANE_FLIP_PENDING(pipe);
|
||||
i8xx_handle_vblank(dev, plane, pipe, iir))
|
||||
flip_mask &= ~DISPLAY_PLANE_FLIP_PENDING(plane);
|
||||
|
||||
if (pipe_stats[pipe] & PIPE_CRC_DONE_INTERRUPT_STATUS)
|
||||
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.gen6_pmimr = I915_READ(GEN6_PMIMR);
|
||||
|
||||
ironlake_disable_display_irq(dev_priv, ~DE_PCH_EVENT_IVB);
|
||||
ibx_disable_display_interrupt(dev_priv, ~SDE_HOTPLUG_MASK_CPT);
|
||||
ironlake_disable_display_irq(dev_priv, 0xffffffff);
|
||||
ibx_disable_display_interrupt(dev_priv, 0xffffffff);
|
||||
ilk_disable_gt_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;
|
||||
unsigned long irqflags;
|
||||
uint32_t val, expected;
|
||||
uint32_t val;
|
||||
|
||||
spin_lock_irqsave(&dev_priv->irq_lock, irqflags);
|
||||
|
||||
val = I915_READ(DEIMR);
|
||||
expected = ~DE_PCH_EVENT_IVB;
|
||||
WARN(val != expected, "DEIMR is 0x%08x, not 0x%08x\n", val, expected);
|
||||
WARN(val != 0xffffffff, "DEIMR is 0x%08x\n", val);
|
||||
|
||||
val = I915_READ(SDEIMR) & ~SDE_HOTPLUG_MASK_CPT;
|
||||
expected = ~SDE_HOTPLUG_MASK_CPT;
|
||||
WARN(val != expected, "SDEIMR non-HPD bits are 0x%08x, not 0x%08x\n",
|
||||
val, expected);
|
||||
val = I915_READ(SDEIMR);
|
||||
WARN(val != 0xffffffff, "SDEIMR is 0x%08x\n", val);
|
||||
|
||||
val = I915_READ(GTIMR);
|
||||
expected = 0xffffffff;
|
||||
WARN(val != expected, "GTIMR is 0x%08x, not 0x%08x\n", val, expected);
|
||||
WARN(val != 0xffffffff, "GTIMR is 0x%08x\n", val);
|
||||
|
||||
val = I915_READ(GEN6_PMIMR);
|
||||
expected = 0xffffffff;
|
||||
WARN(val != expected, "GEN6_PMIMR is 0x%08x, not 0x%08x\n", val,
|
||||
expected);
|
||||
WARN(val != 0xffffffff, "GEN6_PMIMR is 0x%08x\n", val);
|
||||
|
||||
dev_priv->pc8.irqs_disabled = false;
|
||||
|
||||
ironlake_enable_display_irq(dev_priv, ~dev_priv->pc8.regsave.deimr);
|
||||
ibx_enable_display_interrupt(dev_priv,
|
||||
~dev_priv->pc8.regsave.sdeimr &
|
||||
~SDE_HOTPLUG_MASK_CPT);
|
||||
ibx_enable_display_interrupt(dev_priv, ~dev_priv->pc8.regsave.sdeimr);
|
||||
ilk_enable_gt_irq(dev_priv, ~dev_priv->pc8.regsave.gtimr);
|
||||
snb_enable_pm_irq(dev_priv, ~dev_priv->pc8.regsave.gen6_pmimr);
|
||||
I915_WRITE(GTIER, dev_priv->pc8.regsave.gtier);
|
||||
|
|
|
@ -362,6 +362,7 @@
|
|||
#define IOSF_PORT_CCK 0x14
|
||||
#define IOSF_PORT_CCU 0xA9
|
||||
#define IOSF_PORT_GPS_CORE 0x48
|
||||
#define IOSF_PORT_FLISDSI 0x1B
|
||||
#define VLV_IOSF_DATA (VLV_DISPLAY_BASE + 0x2104)
|
||||
#define VLV_IOSF_ADDR (VLV_DISPLAY_BASE + 0x2108)
|
||||
|
||||
|
@ -734,6 +735,8 @@
|
|||
#define HWSTAM 0x02098
|
||||
#define DMA_FADD_I8XX 0x020d0
|
||||
#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 GEN7_ERR_INT 0x44040
|
||||
|
@ -924,7 +927,6 @@
|
|||
#define CM0_COLOR_EVICT_DISABLE (1<<3)
|
||||
#define CM0_DEPTH_WRITE_DISABLE (1<<1)
|
||||
#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_GEN6 0x101008
|
||||
#define GFX_FLSH_CNTL_EN (1<<0)
|
||||
|
@ -1001,6 +1003,7 @@
|
|||
|
||||
#define GEN7_FF_THREAD_MODE 0x20a0
|
||||
#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_HS0 (0x3<<16)
|
||||
#define GEN7_FF_TS_SCHED_LOAD_BALANCE (0x1<<16)
|
||||
|
@ -1028,14 +1031,14 @@
|
|||
#define FBC_CTL_UNCOMPRESSIBLE (1<<14)
|
||||
#define FBC_CTL_C3_IDLE (1<<13)
|
||||
#define FBC_CTL_STRIDE_SHIFT (5)
|
||||
#define FBC_CTL_FENCENO (1<<0)
|
||||
#define FBC_CTL_FENCENO_SHIFT (0)
|
||||
#define FBC_COMMAND 0x0320c
|
||||
#define FBC_CMD_COMPRESS (1<<0)
|
||||
#define FBC_STATUS 0x03210
|
||||
#define FBC_STAT_COMPRESSING (1<<31)
|
||||
#define FBC_STAT_COMPRESSED (1<<30)
|
||||
#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_CTL_FENCE_DBL (0<<4)
|
||||
#define FBC_CTL_IDLE_IMM (0<<2)
|
||||
|
@ -4165,6 +4168,10 @@
|
|||
#define GEN7_L3SQCREG4 0xb034
|
||||
#define L3SQ_URB_READ_CAM_MATCH_DISABLE (1<<27)
|
||||
|
||||
/* GEN8 chicken */
|
||||
#define HDC_CHICKEN0 0x7300
|
||||
#define HDC_FORCE_NON_COHERENT (1<<4)
|
||||
|
||||
/* WaCatErrorRejectionIssue */
|
||||
#define GEN7_SQ_CHICKEN_MBCUNIT_CONFIG 0x9030
|
||||
#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;
|
||||
u64 raw_time; /* 32b value may overflow during fixed point math */
|
||||
u64 units = 128ULL, div = 100000ULL, bias = 100ULL;
|
||||
u32 ret;
|
||||
|
||||
if (!intel_enable_rc6(dev))
|
||||
return 0;
|
||||
|
||||
intel_runtime_pm_get(dev_priv);
|
||||
|
||||
/* On VLV, residency time is in CZ units rather than 1.28us */
|
||||
if (IS_VALLEYVIEW(dev)) {
|
||||
u32 clkctl2;
|
||||
|
@ -52,7 +55,8 @@ static u32 calc_residency(struct drm_device *dev, const u32 reg)
|
|||
CLK_CTL2_CZCOUNT_30NS_SHIFT;
|
||||
if (!clkctl2) {
|
||||
WARN(!clkctl2, "bogus CZ count value");
|
||||
return 0;
|
||||
ret = 0;
|
||||
goto out;
|
||||
}
|
||||
units = DIV_ROUND_UP_ULL(30ULL * bias, (u64)clkctl2);
|
||||
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;
|
||||
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
|
||||
|
@ -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);
|
||||
if (ret)
|
||||
return ret;
|
||||
intel_runtime_pm_get(dev_priv);
|
||||
rp_state_cap = I915_READ(GEN6_RP_STATE_CAP);
|
||||
intel_runtime_pm_put(dev_priv);
|
||||
mutex_unlock(&dev->struct_mutex);
|
||||
|
||||
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) {
|
||||
case 2:
|
||||
return alternate ? 66 : 48;
|
||||
return alternate ? 66667 : 48000;
|
||||
case 3:
|
||||
case 4:
|
||||
return alternate ? 100 : 96;
|
||||
return alternate ? 100000 : 96000;
|
||||
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,
|
||||
!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++) {
|
||||
struct ddi_vbt_port_info *info =
|
||||
|
|
|
@ -39,7 +39,7 @@ struct vbt_header {
|
|||
u8 reserved0;
|
||||
u32 bdb_offset; /**< from beginning of VBT */
|
||||
u32 aim_offset[4]; /**< from beginning of VBT */
|
||||
} __attribute__((packed));
|
||||
} __packed;
|
||||
|
||||
struct bdb_header {
|
||||
u8 signature[16]; /**< Always 'BIOS_DATA_BLOCK' */
|
||||
|
@ -65,7 +65,7 @@ struct vbios_data {
|
|||
u8 rsvd4; /* popup memory size */
|
||||
u8 resize_pci_bios;
|
||||
u8 rsvd5; /* is crt already on ddc2 */
|
||||
} __attribute__((packed));
|
||||
} __packed;
|
||||
|
||||
/*
|
||||
* 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_freq:1; /* SSC freq for PCH attached eDP */
|
||||
u8 rsvd11:3; /* finish byte */
|
||||
} __attribute__((packed));
|
||||
} __packed;
|
||||
|
||||
/* pre-915 */
|
||||
#define GPIO_PIN_DVI_LVDS 0x03 /* "DVI/LVDS DDC GPIO pins" */
|
||||
|
@ -225,7 +225,7 @@ struct old_child_dev_config {
|
|||
u8 dvo2_wiring;
|
||||
u16 extended_type;
|
||||
u8 dvo_function;
|
||||
} __attribute__((packed));
|
||||
} __packed;
|
||||
|
||||
/* 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,
|
||||
|
@ -238,7 +238,7 @@ struct common_child_dev_config {
|
|||
u8 not_common2[2];
|
||||
u8 ddc_pin;
|
||||
u16 edid_ptr;
|
||||
} __attribute__((packed));
|
||||
} __packed;
|
||||
|
||||
/* 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. */
|
||||
|
@ -279,7 +279,7 @@ struct bdb_general_definitions {
|
|||
* sizeof(child_device_config);
|
||||
*/
|
||||
union child_device_config devices[0];
|
||||
} __attribute__((packed));
|
||||
} __packed;
|
||||
|
||||
struct bdb_lvds_options {
|
||||
u8 panel_type;
|
||||
|
@ -293,7 +293,7 @@ struct bdb_lvds_options {
|
|||
u8 lvds_edid:1;
|
||||
u8 rsvd2:1;
|
||||
u8 rsvd4;
|
||||
} __attribute__((packed));
|
||||
} __packed;
|
||||
|
||||
/* LFP pointer table contains entries to the struct below */
|
||||
struct bdb_lvds_lfp_data_ptr {
|
||||
|
@ -303,12 +303,12 @@ struct bdb_lvds_lfp_data_ptr {
|
|||
u8 dvo_table_size;
|
||||
u16 panel_pnp_id_offset;
|
||||
u8 pnp_table_size;
|
||||
} __attribute__((packed));
|
||||
} __packed;
|
||||
|
||||
struct bdb_lvds_lfp_data_ptrs {
|
||||
u8 lvds_entries; /* followed by one or more lvds_data_ptr structs */
|
||||
struct bdb_lvds_lfp_data_ptr ptr[16];
|
||||
} __attribute__((packed));
|
||||
} __packed;
|
||||
|
||||
/* LFP data has 3 blocks per entry */
|
||||
struct lvds_fp_timing {
|
||||
|
@ -325,7 +325,7 @@ struct lvds_fp_timing {
|
|||
u32 pfit_reg;
|
||||
u32 pfit_reg_val;
|
||||
u16 terminator;
|
||||
} __attribute__((packed));
|
||||
} __packed;
|
||||
|
||||
struct lvds_dvo_timing {
|
||||
u16 clock; /**< In 10khz */
|
||||
|
@ -353,7 +353,7 @@ struct lvds_dvo_timing {
|
|||
u8 vsync_positive:1;
|
||||
u8 hsync_positive:1;
|
||||
u8 rsvd2:1;
|
||||
} __attribute__((packed));
|
||||
} __packed;
|
||||
|
||||
struct lvds_pnp_id {
|
||||
u16 mfg_name;
|
||||
|
@ -361,17 +361,17 @@ struct lvds_pnp_id {
|
|||
u32 serial;
|
||||
u8 mfg_week;
|
||||
u8 mfg_year;
|
||||
} __attribute__((packed));
|
||||
} __packed;
|
||||
|
||||
struct bdb_lvds_lfp_data_entry {
|
||||
struct lvds_fp_timing fp_timing;
|
||||
struct lvds_dvo_timing dvo_timing;
|
||||
struct lvds_pnp_id pnp_id;
|
||||
} __attribute__((packed));
|
||||
} __packed;
|
||||
|
||||
struct bdb_lvds_lfp_data {
|
||||
struct bdb_lvds_lfp_data_entry data[16];
|
||||
} __attribute__((packed));
|
||||
} __packed;
|
||||
|
||||
struct aimdb_header {
|
||||
char signature[16];
|
||||
|
@ -379,12 +379,12 @@ struct aimdb_header {
|
|||
u16 aimdb_version;
|
||||
u16 aimdb_header_size;
|
||||
u16 aimdb_size;
|
||||
} __attribute__((packed));
|
||||
} __packed;
|
||||
|
||||
struct aimdb_block {
|
||||
u8 aimdb_id;
|
||||
u16 aimdb_size;
|
||||
} __attribute__((packed));
|
||||
} __packed;
|
||||
|
||||
struct vch_panel_data {
|
||||
u16 fp_timing_offset;
|
||||
|
@ -395,12 +395,12 @@ struct vch_panel_data {
|
|||
u8 text_fitting_size;
|
||||
u16 graphics_fitting_offset;
|
||||
u8 graphics_fitting_size;
|
||||
} __attribute__((packed));
|
||||
} __packed;
|
||||
|
||||
struct vch_bdb_22 {
|
||||
struct aimdb_block aimdb_block;
|
||||
struct vch_panel_data panels[16];
|
||||
} __attribute__((packed));
|
||||
} __packed;
|
||||
|
||||
struct bdb_sdvo_lvds_options {
|
||||
u8 panel_backlight;
|
||||
|
@ -416,7 +416,7 @@ struct bdb_sdvo_lvds_options {
|
|||
u8 panel_misc_bits_2;
|
||||
u8 panel_misc_bits_3;
|
||||
u8 panel_misc_bits_4;
|
||||
} __attribute__((packed));
|
||||
} __packed;
|
||||
|
||||
|
||||
#define BDB_DRIVER_FEATURE_NO_LVDS 0
|
||||
|
@ -462,7 +462,7 @@ struct bdb_driver_features {
|
|||
|
||||
u8 hdmi_termination;
|
||||
u8 custom_vbt_version;
|
||||
} __attribute__((packed));
|
||||
} __packed;
|
||||
|
||||
#define EDP_18BPP 0
|
||||
#define EDP_24BPP 1
|
||||
|
@ -487,14 +487,14 @@ struct edp_power_seq {
|
|||
u16 t9;
|
||||
u16 t10;
|
||||
u16 t11_t12;
|
||||
} __attribute__ ((packed));
|
||||
} __packed;
|
||||
|
||||
struct edp_link_params {
|
||||
u8 rate:4;
|
||||
u8 lanes:4;
|
||||
u8 preemphasis:4;
|
||||
u8 vswing:4;
|
||||
} __attribute__ ((packed));
|
||||
} __packed;
|
||||
|
||||
struct bdb_edp {
|
||||
struct edp_power_seq power_seqs[16];
|
||||
|
@ -505,7 +505,7 @@ struct bdb_edp {
|
|||
/* ith bit indicates enabled/disabled for (i+1)th panel */
|
||||
u16 edp_s3d_feature;
|
||||
u16 edp_t3_optimization;
|
||||
} __attribute__ ((packed));
|
||||
} __packed;
|
||||
|
||||
void intel_setup_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 lp_byte_clk;
|
||||
u32 clk_lane_switch_cnt;
|
||||
} __attribute__((packed));
|
||||
} __packed;
|
||||
|
||||
#endif /* _I830_BIOS_H_ */
|
||||
|
|
|
@ -73,7 +73,7 @@ static const u32 hsw_ddi_translations_hdmi[] = {
|
|||
};
|
||||
|
||||
static const u32 bdw_ddi_translations_edp[] = {
|
||||
0x00FFFFFF, 0x00000012, /* DP parameters */
|
||||
0x00FFFFFF, 0x00000012, /* eDP parameters */
|
||||
0x00EBAFFF, 0x00020011,
|
||||
0x00C71FFF, 0x0006000F,
|
||||
0x00FFFFFF, 0x00020011,
|
||||
|
@ -696,21 +696,23 @@ intel_ddi_calculate_wrpll(int clock /* in Hz */,
|
|||
*n2_out = best.n2;
|
||||
*p_out = best.p;
|
||||
*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 drm_encoder *encoder = &intel_encoder->base;
|
||||
struct drm_i915_private *dev_priv = crtc->dev->dev_private;
|
||||
struct intel_ddi_plls *plls = &dev_priv->ddi_plls;
|
||||
int type = intel_encoder->type;
|
||||
enum pipe pipe = intel_crtc->pipe;
|
||||
uint32_t reg, val;
|
||||
int clock = intel_crtc->config.port_clock;
|
||||
|
||||
intel_ddi_put_crtc_pll(crtc);
|
||||
|
@ -734,10 +736,8 @@ bool intel_ddi_pll_mode_set(struct drm_crtc *crtc)
|
|||
return false;
|
||||
}
|
||||
|
||||
/* We don't need to turn any PLL on because we'll use LCPLL. */
|
||||
return true;
|
||||
|
||||
} else if (type == INTEL_OUTPUT_HDMI) {
|
||||
uint32_t reg, val;
|
||||
unsigned p, n2, r2;
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
DRM_DEBUG_KMS("WRPLL: %dKHz refresh rate with p=%d, n2=%d r2=%d\n",
|
||||
clock, p, n2, r2);
|
||||
|
||||
if (reg == WRPLL_CTL1) {
|
||||
plls->wrpll1_refcount++;
|
||||
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",
|
||||
pipe_name(pipe));
|
||||
plls->spll_refcount++;
|
||||
reg = SPLL_CTL;
|
||||
intel_crtc->ddi_pll_sel = PORT_CLK_SEL_SPLL;
|
||||
} else {
|
||||
DRM_ERROR("SPLL already in use\n");
|
||||
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 {
|
||||
WARN(1, "Invalid DDI encoder type %d\n", type);
|
||||
return false;
|
||||
}
|
||||
|
||||
I915_WRITE(reg, val);
|
||||
udelay(20);
|
||||
|
||||
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)
|
||||
{
|
||||
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) {
|
||||
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_vdd_off(intel_dp, true);
|
||||
}
|
||||
|
||||
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) {
|
||||
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);
|
||||
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 = {
|
||||
.dot = { .min = 25000, .max = 350000 },
|
||||
.vco = { .min = 930000, .max = 1400000 },
|
||||
.n = { .min = 3, .max = 16 },
|
||||
.vco = { .min = 908000, .max = 1512000 },
|
||||
.n = { .min = 2, .max = 16 },
|
||||
.m = { .min = 96, .max = 140 },
|
||||
.m1 = { .min = 18, .max = 26 },
|
||||
.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 = {
|
||||
.dot = { .min = 25000, .max = 350000 },
|
||||
.vco = { .min = 930000, .max = 1400000 },
|
||||
.n = { .min = 3, .max = 16 },
|
||||
.vco = { .min = 908000, .max = 1512000 },
|
||||
.n = { .min = 2, .max = 16 },
|
||||
.m = { .min = 96, .max = 140 },
|
||||
.m1 = { .min = 18, .max = 26 },
|
||||
.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 = {
|
||||
.dot = { .min = 25000, .max = 350000 },
|
||||
.vco = { .min = 930000, .max = 1400000 },
|
||||
.n = { .min = 3, .max = 16 },
|
||||
.vco = { .min = 908000, .max = 1512000 },
|
||||
.n = { .min = 2, .max = 16 },
|
||||
.m = { .min = 96, .max = 140 },
|
||||
.m1 = { .min = 18, .max = 26 },
|
||||
.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->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->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->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->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->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->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))
|
||||
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;
|
||||
/*
|
||||
* 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;
|
||||
} else if (intel_pipe_has_type(crtc, INTEL_OUTPUT_LVDS) &&
|
||||
intel_panel_use_ssc(dev_priv) && num_connectors < 2) {
|
||||
refclk = dev_priv->vbt.lvds_ssc_freq * 1000;
|
||||
DRM_DEBUG_KMS("using SSC reference clock of %d MHz\n",
|
||||
refclk / 1000);
|
||||
refclk = dev_priv->vbt.lvds_ssc_freq;
|
||||
DRM_DEBUG_KMS("using SSC reference clock of %d kHz\n", refclk);
|
||||
} else if (!IS_GEN2(dev)) {
|
||||
refclk = 96000;
|
||||
} 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) {
|
||||
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);
|
||||
return dev_priv->vbt.lvds_ssc_freq * 1000;
|
||||
return dev_priv->vbt.lvds_ssc_freq;
|
||||
}
|
||||
|
||||
return 120000;
|
||||
|
@ -6163,7 +6172,7 @@ static uint32_t ironlake_compute_dpll(struct intel_crtc *intel_crtc,
|
|||
factor = 21;
|
||||
if (is_lvds) {
|
||||
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)))
|
||||
factor = 25;
|
||||
} 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;
|
||||
|
||||
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));
|
||||
|
||||
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);
|
||||
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);
|
||||
val = I915_READ(SDEIMR);
|
||||
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;
|
||||
uint32_t val;
|
||||
|
||||
WARN_ON(!HAS_PC8(dev));
|
||||
|
||||
if (dev_priv->pc8.enabled)
|
||||
return;
|
||||
|
||||
|
@ -6644,6 +6655,8 @@ void hsw_enable_pc8_work(struct work_struct *__work)
|
|||
lpt_disable_clkout_dp(dev);
|
||||
hsw_pc8_disable_interrupts(dev);
|
||||
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)
|
||||
|
@ -6673,12 +6686,16 @@ static void __hsw_disable_package_c8(struct drm_i915_private *dev_priv)
|
|||
if (dev_priv->pc8.disable_count != 1)
|
||||
return;
|
||||
|
||||
WARN_ON(!HAS_PC8(dev));
|
||||
|
||||
cancel_delayed_work_sync(&dev_priv->pc8.enable_work);
|
||||
if (!dev_priv->pc8.enabled)
|
||||
return;
|
||||
|
||||
DRM_DEBUG_KMS("Disabling package C8+\n");
|
||||
|
||||
intel_runtime_pm_get(dev_priv);
|
||||
|
||||
hsw_restore_lcpll(dev_priv);
|
||||
hsw_pc8_restore_interrupts(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 ret;
|
||||
|
||||
if (!intel_ddi_pll_mode_set(crtc))
|
||||
if (!intel_ddi_pll_select(intel_crtc))
|
||||
return -EINVAL;
|
||||
intel_ddi_pll_enable(intel_crtc);
|
||||
|
||||
if (intel_crtc->config.has_dp_encoder)
|
||||
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;
|
||||
|
||||
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))
|
||||
return 120000;
|
||||
else if (!IS_GEN2(dev))
|
||||
|
@ -7933,12 +7951,17 @@ static void i9xx_crtc_clock_get(struct intel_crtc *crtc,
|
|||
else
|
||||
i9xx_clock(refclk, &clock);
|
||||
} 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) {
|
||||
clock.p1 = ffs((dpll & DPLL_FPA01_P1_POST_DIV_MASK_I830_LVDS) >>
|
||||
DPLL_FPA01_P1_POST_DIV_SHIFT);
|
||||
clock.p2 = 14;
|
||||
|
||||
if (lvds & LVDS_CLKB_POWER_UP)
|
||||
clock.p2 = 7;
|
||||
else
|
||||
clock.p2 = 14;
|
||||
} else {
|
||||
if (dpll & PLL_P1_DIVIDE_BY_TWO)
|
||||
clock.p1 = 2;
|
||||
|
@ -10122,10 +10145,13 @@ static void intel_crtc_init(struct drm_device *dev, int pipe)
|
|||
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->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");
|
||||
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)
|
||||
{
|
||||
struct drm_i915_private *dev_priv = dev->dev_private;
|
||||
|
||||
intel_prepare_ddi(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);
|
||||
|
||||
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_ctrl_reg));
|
||||
}
|
||||
|
||||
DRM_DEBUG_KMS("Wait complete\n");
|
||||
}
|
||||
|
||||
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))
|
||||
return;
|
||||
|
||||
intel_runtime_pm_get(dev_priv);
|
||||
|
||||
DRM_DEBUG_KMS("Turning eDP VDD on\n");
|
||||
|
||||
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 */
|
||||
DRM_DEBUG_KMS("PP_STATUS: 0x%08x PP_CONTROL: 0x%08x\n",
|
||||
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");
|
||||
|
||||
WARN(!intel_dp->want_panel_vdd, "Need VDD to turn off panel\n");
|
||||
|
||||
pp = ironlake_get_pp_control(intel_dp);
|
||||
/* We need to switch off panel power _and_ force vdd, for otherwise some
|
||||
* 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);
|
||||
|
||||
I915_WRITE(pp_ctrl_reg, pp);
|
||||
POSTING_READ(pp_ctrl_reg);
|
||||
|
||||
intel_dp->want_panel_vdd = false;
|
||||
|
||||
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
|
||||
* ensure that we have vdd while we switch off the panel. */
|
||||
ironlake_edp_panel_vdd_on(intel_dp);
|
||||
ironlake_edp_backlight_off(intel_dp);
|
||||
intel_dp_sink_dpms(intel_dp, DRM_MODE_DPMS_OFF);
|
||||
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);
|
||||
}
|
||||
|
||||
#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
|
||||
* 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_encoder *intel_encoder = &intel_dig_port->base;
|
||||
struct drm_device *dev = connector->dev;
|
||||
struct drm_i915_private *dev_priv = dev->dev_private;
|
||||
enum drm_connector_status status;
|
||||
struct edid *edid = NULL;
|
||||
|
||||
intel_runtime_pm_get(dev_priv);
|
||||
|
||||
DRM_DEBUG_KMS("[CONNECTOR:%d:%s]\n",
|
||||
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);
|
||||
|
||||
if (status != connector_status_connected)
|
||||
return status;
|
||||
goto out;
|
||||
|
||||
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)
|
||||
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)
|
||||
|
|
|
@ -155,6 +155,7 @@ struct intel_encoder {
|
|||
|
||||
struct intel_panel {
|
||||
struct drm_display_mode *fixed_mode;
|
||||
struct drm_display_mode *downclock_mode;
|
||||
int fitting_mode;
|
||||
|
||||
/* backlight */
|
||||
|
@ -454,7 +455,7 @@ struct intel_hdmi {
|
|||
bool rgb_quant_range_selectable;
|
||||
void (*write_infoframe)(struct drm_encoder *encoder,
|
||||
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,
|
||||
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_disable_pipe_clock(struct intel_crtc *intel_crtc);
|
||||
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_set_pipe_settings(struct drm_crtc *crtc);
|
||||
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,
|
||||
int dotclock);
|
||||
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_disable_ips(struct intel_crtc *crtc);
|
||||
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_init_backlight_funcs(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 */
|
||||
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 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_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);
|
||||
|
||||
|
||||
|
|
|
@ -37,49 +37,18 @@
|
|||
static const struct intel_dsi_device intel_dsi_devices[] = {
|
||||
};
|
||||
|
||||
|
||||
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)
|
||||
static void band_gap_reset(struct drm_i915_private *dev_priv)
|
||||
{
|
||||
mutex_lock(&dev_priv->dpio_lock);
|
||||
|
||||
/* Enable bandgap fix in GOP driver */
|
||||
vlv_cck_modify(dev_priv, 0x6D, 0x00010000, 0x00030000);
|
||||
msleep(20);
|
||||
vlv_cck_modify(dev_priv, 0x6E, 0x00010000, 0x00030000);
|
||||
msleep(20);
|
||||
vlv_cck_modify(dev_priv, 0x6F, 0x00010000, 0x00030000);
|
||||
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);
|
||||
vlv_flisdsi_write(dev_priv, 0x08, 0x0001);
|
||||
vlv_flisdsi_write(dev_priv, 0x0F, 0x0005);
|
||||
vlv_flisdsi_write(dev_priv, 0x0F, 0x0025);
|
||||
udelay(150);
|
||||
vlv_flisdsi_write(dev_priv, 0x0F, 0x0000);
|
||||
vlv_flisdsi_write(dev_priv, 0x08, 0x0000);
|
||||
|
||||
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)
|
||||
|
@ -132,14 +101,47 @@ static void intel_dsi_pre_pll_enable(struct intel_encoder *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)
|
||||
{
|
||||
struct intel_dsi *intel_dsi = enc_to_intel_dsi(&encoder->base);
|
||||
|
||||
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)
|
||||
{
|
||||
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_dsi *intel_dsi = enc_to_intel_dsi(&encoder->base);
|
||||
int pipe = intel_crtc->pipe;
|
||||
|
@ -147,41 +149,28 @@ static void intel_dsi_enable(struct intel_encoder *encoder)
|
|||
|
||||
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))
|
||||
I915_WRITE(MIPI_MAX_RETURN_PKT_SIZE(pipe), 8 * 4);
|
||||
|
||||
if (is_vid_mode(intel_dsi)) {
|
||||
else {
|
||||
msleep(20); /* XXX */
|
||||
dpi_send_cmd(intel_dsi, TURN_ON);
|
||||
msleep(100);
|
||||
|
||||
/* 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);
|
||||
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)
|
||||
{
|
||||
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_dsi *intel_dsi = enc_to_intel_dsi(&encoder->base);
|
||||
int pipe = intel_crtc->pipe;
|
||||
|
@ -189,8 +178,6 @@ static void intel_dsi_disable(struct intel_encoder *encoder)
|
|||
|
||||
DRM_DEBUG_KMS("\n");
|
||||
|
||||
intel_dsi->dev.dev_ops->disable(&intel_dsi->dev);
|
||||
|
||||
if (is_vid_mode(intel_dsi)) {
|
||||
dpi_send_cmd(intel_dsi, SHUTDOWN);
|
||||
msleep(10);
|
||||
|
@ -203,20 +190,54 @@ static void intel_dsi_disable(struct intel_encoder *encoder)
|
|||
msleep(2);
|
||||
}
|
||||
|
||||
temp = I915_READ(MIPI_DEVICE_READY(pipe));
|
||||
if (temp & DEVICE_READY) {
|
||||
temp &= ~DEVICE_READY;
|
||||
temp &= ~ULPS_STATE_MASK;
|
||||
I915_WRITE(MIPI_DEVICE_READY(pipe), temp);
|
||||
}
|
||||
/* if disable packets are sent before sending shutdown packet then in
|
||||
* some next enable sequence send turn on packet error is observed */
|
||||
if (intel_dsi->dev.dev_ops->disable)
|
||||
intel_dsi->dev.dev_ops->disable(&intel_dsi->dev);
|
||||
}
|
||||
|
||||
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");
|
||||
|
||||
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);
|
||||
}
|
||||
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,
|
||||
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));
|
||||
|
||||
/* Update the DSI PLL */
|
||||
vlv_enable_dsi_pll(intel_encoder);
|
||||
|
||||
/* 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
|
||||
* 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_EN(pipe), 0xffffffff);
|
||||
|
||||
I915_WRITE(MIPI_DPHY_PARAM(pipe),
|
||||
0x3c << EXIT_ZERO_COUNT_SHIFT |
|
||||
0x1f << TRAIL_COUNT_SHIFT |
|
||||
0xc5 << CLK_ZERO_COUNT_SHIFT |
|
||||
0x1f << PREPARE_COUNT_SHIFT);
|
||||
I915_WRITE(MIPI_DPHY_PARAM(pipe), intel_dsi->dphy_reg);
|
||||
|
||||
I915_WRITE(MIPI_DPI_RESOLUTION(pipe),
|
||||
adjusted_mode->vdisplay << VERTICAL_ADDRESS_SHIFT |
|
||||
|
@ -426,9 +440,9 @@ static void intel_dsi_mode_set(struct intel_encoder *intel_encoder)
|
|||
adjusted_mode->htotal,
|
||||
bpp, intel_dsi->lane_count) + 1);
|
||||
}
|
||||
I915_WRITE(MIPI_LP_RX_TIMEOUT(pipe), 8309); /* max */
|
||||
I915_WRITE(MIPI_TURN_AROUND_TIMEOUT(pipe), 0x14); /* max */
|
||||
I915_WRITE(MIPI_DEVICE_RESET_TIMER(pipe), 0xffff); /* max */
|
||||
I915_WRITE(MIPI_LP_RX_TIMEOUT(pipe), intel_dsi->lp_rx_timeout);
|
||||
I915_WRITE(MIPI_TURN_AROUND_TIMEOUT(pipe), intel_dsi->turn_arnd_val);
|
||||
I915_WRITE(MIPI_DEVICE_RESET_TIMER(pipe), intel_dsi->rst_timer_val);
|
||||
|
||||
/* dphy stuff */
|
||||
|
||||
|
@ -443,29 +457,31 @@ static void intel_dsi_mode_set(struct intel_encoder *intel_encoder)
|
|||
*
|
||||
* 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
|
||||
* of byte clocks occupied in one low power clock. based on txbyteclkhs
|
||||
* and txclkesc. txclkesc time / txbyteclk time * (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
|
||||
* bytes meant for dcs write memory command is programmed in this
|
||||
* 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
|
||||
* 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),
|
||||
0xa << LP_HS_SSW_CNT_SHIFT |
|
||||
0x14 << HS_LP_PWR_SW_CNT_SHIFT);
|
||||
intel_dsi->clk_lp_to_hs_count << LP_HS_SSW_CNT_SHIFT |
|
||||
intel_dsi->clk_hs_to_lp_count << HS_LP_PWR_SW_CNT_SHIFT);
|
||||
|
||||
if (is_vid_mode(intel_dsi))
|
||||
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
|
||||
|
|
|
@ -39,6 +39,13 @@ struct intel_dsi_device {
|
|||
struct intel_dsi_dev_ops {
|
||||
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 */
|
||||
void (*enable)(struct intel_dsi_device *dsi);
|
||||
|
||||
|
@ -89,6 +96,20 @@ struct intel_dsi {
|
|||
|
||||
/* eot for MIPI_EOT_DISABLE register */
|
||||
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)
|
||||
|
|
|
@ -50,6 +50,8 @@ static const u32 lfsr_converts[] = {
|
|||
71, 35 /* 91 - 92 */
|
||||
};
|
||||
|
||||
#ifdef DSI_CLK_FROM_RR
|
||||
|
||||
static u32 dsi_rr_formula(const struct drm_display_mode *mode,
|
||||
int pixel_format, int video_mode_format,
|
||||
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 */
|
||||
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)
|
||||
dsi_clk *= 2;
|
||||
|
@ -129,64 +131,37 @@ static u32 dsi_rr_formula(const struct drm_display_mode *mode,
|
|||
return dsi_clk;
|
||||
}
|
||||
|
||||
#ifdef MNP_FROM_TABLE
|
||||
#else
|
||||
|
||||
struct dsi_clock_table {
|
||||
u32 freq;
|
||||
u8 m;
|
||||
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)
|
||||
/* Get DSI clock from pixel clock */
|
||||
static u32 dsi_clk_from_pclk(const struct drm_display_mode *mode,
|
||||
int pixel_format, int lane_count)
|
||||
{
|
||||
unsigned int i;
|
||||
u8 m;
|
||||
u8 n;
|
||||
u8 p;
|
||||
u32 m_seed;
|
||||
u32 dsi_clk_khz;
|
||||
u32 bpp;
|
||||
|
||||
if (dsi_clk < 300 || dsi_clk > 1000)
|
||||
return -ECHRNG;
|
||||
|
||||
for (i = 0; i <= ARRAY_SIZE(dsi_clk_tbl); i++) {
|
||||
if (dsi_clk_tbl[i].freq > dsi_clk)
|
||||
break;
|
||||
switch (pixel_format) {
|
||||
default:
|
||||
case VID_MODE_FORMAT_RGB888:
|
||||
case VID_MODE_FORMAT_RGB666_LOOSE:
|
||||
bpp = 24;
|
||||
break;
|
||||
case VID_MODE_FORMAT_RGB666:
|
||||
bpp = 18;
|
||||
break;
|
||||
case VID_MODE_FORMAT_RGB565:
|
||||
bpp = 16;
|
||||
break;
|
||||
}
|
||||
|
||||
m = dsi_clk_tbl[i].m;
|
||||
p = dsi_clk_tbl[i].p;
|
||||
m_seed = lfsr_converts[m - 62];
|
||||
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;
|
||||
/* DSI data rate = pixel clock * bits per pixel / lane count
|
||||
pixel clock is converted from KHz to Hz */
|
||||
dsi_clk_khz = DIV_ROUND_CLOSEST(mode->clock * bpp, lane_count);
|
||||
|
||||
return 0;
|
||||
return dsi_clk_khz;
|
||||
}
|
||||
|
||||
#else
|
||||
#endif
|
||||
|
||||
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 error;
|
||||
u32 tmp_error;
|
||||
u32 target_dsi_clk;
|
||||
u32 calc_dsi_clk;
|
||||
int target_dsi_clk;
|
||||
int calc_dsi_clk;
|
||||
u32 calc_m;
|
||||
u32 calc_p;
|
||||
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");
|
||||
return -ECHRNG;
|
||||
}
|
||||
|
||||
ref_clk = 25000;
|
||||
target_dsi_clk = dsi_clk * 1000;
|
||||
target_dsi_clk = dsi_clk;
|
||||
error = 0xFFFFFFFF;
|
||||
tmp_error = 0xFFFFFFFF;
|
||||
calc_m = 0;
|
||||
calc_p = 0;
|
||||
|
||||
for (m = 62; m <= 92; m++) {
|
||||
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;
|
||||
if (calc_dsi_clk >= target_dsi_clk) {
|
||||
tmp_error = calc_dsi_clk - target_dsi_clk;
|
||||
if (tmp_error < error) {
|
||||
error = tmp_error;
|
||||
calc_m = m;
|
||||
calc_p = p;
|
||||
}
|
||||
if (calc_dsi_clk == target_dsi_clk) {
|
||||
calc_m = m;
|
||||
calc_p = p;
|
||||
error = 0;
|
||||
break;
|
||||
} 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];
|
||||
|
@ -235,8 +221,6 @@ static int dsi_calc_mnp(u32 dsi_clk, struct dsi_mnp *dsi_mnp)
|
|||
return 0;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
/*
|
||||
* XXX: The muxing and gating is hard coded for now. Need to add support for
|
||||
* 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;
|
||||
u32 dsi_clk;
|
||||
|
||||
dsi_clk = dsi_rr_formula(mode, intel_dsi->pixel_format,
|
||||
intel_dsi->video_mode_format,
|
||||
intel_dsi->lane_count, !intel_dsi->eot_disable);
|
||||
dsi_clk = dsi_clk_from_pclk(mode, intel_dsi->pixel_format,
|
||||
intel_dsi->lane_count);
|
||||
|
||||
ret = dsi_calc_mnp(dsi_clk, &dsi_mnp);
|
||||
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,
|
||||
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_i915_private *dev_priv = dev->dev_private;
|
||||
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,
|
||||
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_i915_private *dev_priv = dev->dev_private;
|
||||
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,
|
||||
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_i915_private *dev_priv = dev->dev_private;
|
||||
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,
|
||||
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_i915_private *dev_priv = dev->dev_private;
|
||||
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,
|
||||
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_i915_private *dev_priv = dev->dev_private;
|
||||
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)
|
||||
goto exit;
|
||||
|
||||
drm_modeset_lock_all(dev);
|
||||
intel_modeset_setup_hw_state(dev, true);
|
||||
drm_modeset_unlock_all(dev);
|
||||
/*
|
||||
* Some old platform's BIOS love to wreak havoc while the lid is closed.
|
||||
* 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;
|
||||
|
||||
|
@ -745,57 +755,6 @@ static const struct dmi_system_id intel_no_lvds[] = {
|
|||
{ } /* 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
|
||||
* the LVDS is present.
|
||||
|
@ -1073,8 +1032,22 @@ void intel_lvds_init(struct drm_device *dev)
|
|||
|
||||
fixed_mode = drm_mode_duplicate(dev, scan);
|
||||
if (fixed_mode) {
|
||||
intel_find_lvds_downclock(dev, fixed_mode,
|
||||
connector);
|
||||
intel_connector->panel.downclock_mode =
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -64,7 +64,7 @@ struct opregion_header {
|
|||
u8 driver_ver[16];
|
||||
u32 mboxes;
|
||||
u8 reserved[164];
|
||||
} __attribute__((packed));
|
||||
} __packed;
|
||||
|
||||
/* OpRegion mailbox #1: public ACPI methods */
|
||||
struct opregion_acpi {
|
||||
|
@ -86,7 +86,7 @@ struct opregion_acpi {
|
|||
u32 cnot; /* current OS notification */
|
||||
u32 nrdy; /* driver status */
|
||||
u8 rsvd2[60];
|
||||
} __attribute__((packed));
|
||||
} __packed;
|
||||
|
||||
/* OpRegion mailbox #2: SWSCI */
|
||||
struct opregion_swsci {
|
||||
|
@ -94,7 +94,7 @@ struct opregion_swsci {
|
|||
u32 parm; /* command parameters */
|
||||
u32 dslp; /* driver sleep time-out */
|
||||
u8 rsvd[244];
|
||||
} __attribute__((packed));
|
||||
} __packed;
|
||||
|
||||
/* OpRegion mailbox #3: ASLE */
|
||||
struct opregion_asle {
|
||||
|
@ -115,7 +115,7 @@ struct opregion_asle {
|
|||
u32 srot; /* supported rotation angles */
|
||||
u32 iuer; /* IUER events */
|
||||
u8 rsvd[86];
|
||||
} __attribute__((packed));
|
||||
} __packed;
|
||||
|
||||
/* Driver readiness indicator */
|
||||
#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 drm_device *dev = connector->base.dev;
|
||||
struct drm_i915_private *dev_priv = dev->dev_private;
|
||||
int ret;
|
||||
|
||||
intel_runtime_pm_get(dev_priv);
|
||||
mutex_lock(&dev->mode_config.mutex);
|
||||
ret = intel_panel_get_backlight(connector);
|
||||
mutex_unlock(&dev->mode_config.mutex);
|
||||
intel_runtime_pm_put(dev_priv);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
@ -1104,6 +1107,59 @@ void intel_panel_destroy_backlight(struct drm_connector *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 */
|
||||
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)
|
||||
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 "../../../platform/x86/intel_ips.h"
|
||||
#include <linux/module.h>
|
||||
#include <linux/vgaarb.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
|
||||
|
@ -86,7 +88,7 @@ static void i8xx_disable_fbc(struct drm_device *dev)
|
|||
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_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);
|
||||
int cfb_pitch;
|
||||
int plane, i;
|
||||
u32 fbc_ctl, fbc_ctl2;
|
||||
u32 fbc_ctl;
|
||||
|
||||
cfb_pitch = dev_priv->fbc.size / FBC_LL_SIZE;
|
||||
if (fb->pitches[0] < cfb_pitch)
|
||||
cfb_pitch = fb->pitches[0];
|
||||
|
||||
/* FBC_CTL wants 64B units */
|
||||
cfb_pitch = (cfb_pitch / 64) - 1;
|
||||
/* FBC_CTL wants 32B or 64B units */
|
||||
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;
|
||||
|
||||
/* Clear old tags */
|
||||
for (i = 0; i < (FBC_LL_SIZE / 32) + 1; i++)
|
||||
I915_WRITE(FBC_TAG + (i * 4), 0);
|
||||
|
||||
/* Set it up... */
|
||||
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);
|
||||
if (IS_GEN4(dev)) {
|
||||
u32 fbc_ctl2;
|
||||
|
||||
/* Set it up... */
|
||||
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... */
|
||||
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))
|
||||
fbc_ctl |= FBC_CTL_C3_IDLE; /* 945 needs special SR handling */
|
||||
fbc_ctl |= (cfb_pitch & 0xff) << FBC_CTL_STRIDE_SHIFT;
|
||||
fbc_ctl |= (interval & 0x2fff) << FBC_CTL_INTERVAL_SHIFT;
|
||||
fbc_ctl |= obj->fence_reg;
|
||||
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;
|
||||
}
|
||||
|
||||
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_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 intel_crtc *intel_crtc = to_intel_crtc(crtc);
|
||||
int plane = intel_crtc->plane == 0 ? DPFC_CTL_PLANEA : DPFC_CTL_PLANEB;
|
||||
unsigned long stall_watermark = 200;
|
||||
u32 dpfc_ctl;
|
||||
|
||||
dpfc_ctl = plane | DPFC_SR_EN | DPFC_CTL_LIMIT_1X;
|
||||
dpfc_ctl |= DPFC_CTL_FENCE_EN | obj->fence_reg;
|
||||
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);
|
||||
|
||||
/* 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);
|
||||
}
|
||||
|
||||
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_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 intel_crtc *intel_crtc = to_intel_crtc(crtc);
|
||||
int plane = intel_crtc->plane == 0 ? DPFC_CTL_PLANEA : DPFC_CTL_PLANEB;
|
||||
unsigned long stall_watermark = 200;
|
||||
u32 dpfc_ctl;
|
||||
|
||||
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;
|
||||
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_FBC_RT_BASE, i915_gem_obj_ggtt_offset(obj) | ILK_FBC_RT_VALID);
|
||||
/* enable it... */
|
||||
|
@ -272,7 +274,7 @@ static bool ironlake_fbc_enabled(struct drm_device *dev)
|
|||
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_i915_private *dev_priv = dev->dev_private;
|
||||
|
@ -329,8 +331,7 @@ static void intel_fbc_work_fn(struct work_struct *__work)
|
|||
* the prior work.
|
||||
*/
|
||||
if (work->crtc->fb == work->fb) {
|
||||
dev_priv->display.enable_fbc(work->crtc,
|
||||
work->interval);
|
||||
dev_priv->display.enable_fbc(work->crtc);
|
||||
|
||||
dev_priv->fbc.plane = to_intel_crtc(work->crtc)->plane;
|
||||
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;
|
||||
}
|
||||
|
||||
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 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);
|
||||
if (work == NULL) {
|
||||
DRM_ERROR("Failed to allocate FBC work structure\n");
|
||||
dev_priv->display.enable_fbc(crtc, interval);
|
||||
dev_priv->display.enable_fbc(crtc);
|
||||
return;
|
||||
}
|
||||
|
||||
work->crtc = crtc;
|
||||
work->fb = crtc->fb;
|
||||
work->interval = interval;
|
||||
INIT_DELAYED_WORK(&work->work, intel_fbc_work_fn);
|
||||
|
||||
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");
|
||||
goto out_disable;
|
||||
}
|
||||
if ((IS_I915GM(dev) || IS_I945GM(dev) || IS_HASWELL(dev)) &&
|
||||
intel_crtc->plane != 0) {
|
||||
if ((INTEL_INFO(dev)->gen < 4 || IS_HASWELL(dev)) &&
|
||||
intel_crtc->plane != PLANE_A) {
|
||||
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;
|
||||
}
|
||||
|
||||
|
@ -602,7 +602,7 @@ void intel_update_fbc(struct drm_device *dev)
|
|||
intel_disable_fbc(dev);
|
||||
}
|
||||
|
||||
intel_enable_fbc(crtc, 500);
|
||||
intel_enable_fbc(crtc);
|
||||
dev_priv->fbc.no_fbc_reason = FBC_OK;
|
||||
return;
|
||||
|
||||
|
@ -5257,19 +5257,33 @@ static void gen8_init_clock_gating(struct drm_device *dev)
|
|||
I915_WRITE(GEN7_HALF_SLICE_CHICKEN1,
|
||||
_MASKED_BIT_ENABLE(GEN7_SINGLE_SUBSCAN_DISPATCH_ENABLE));
|
||||
|
||||
/* WaSwitchSolVfFArbitrationPriority */
|
||||
/* WaSwitchSolVfFArbitrationPriority:bdw */
|
||||
I915_WRITE(GAM_ECOCHK, I915_READ(GAM_ECOCHK) | HSW_ECOCHK_ARB_PRIO_SOL);
|
||||
|
||||
/* WaPsrDPAMaskVBlankInSRD */
|
||||
/* WaPsrDPAMaskVBlankInSRD:bdw */
|
||||
I915_WRITE(CHICKEN_PAR1_1,
|
||||
I915_READ(CHICKEN_PAR1_1) | DPA_MASK_VBLANK_SRD);
|
||||
|
||||
/* WaPsrDPRSUnmaskVBlankInSRD */
|
||||
/* WaPsrDPRSUnmaskVBlankInSRD:bdw */
|
||||
for_each_pipe(i) {
|
||||
I915_WRITE(CHICKEN_PIPESL_1(i),
|
||||
I915_READ(CHICKEN_PIPESL_1(i) |
|
||||
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)
|
||||
|
@ -5681,14 +5695,71 @@ bool intel_display_power_enabled(struct drm_device *dev,
|
|||
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,
|
||||
struct i915_power_well *power_well, bool enable)
|
||||
{
|
||||
struct drm_i915_private *dev_priv = dev->dev_private;
|
||||
bool is_enabled, enable_requested;
|
||||
unsigned long irqflags;
|
||||
uint32_t tmp;
|
||||
|
||||
WARN_ON(dev_priv->pc8.enabled);
|
||||
|
||||
tmp = I915_READ(HSW_PWR_WELL_DRIVER);
|
||||
is_enabled = tmp & HSW_PWR_WELL_STATE_ENABLED;
|
||||
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");
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
hsw_power_well_post_enable(dev_priv);
|
||||
} else {
|
||||
if (enable_requested) {
|
||||
enum pipe p;
|
||||
|
||||
I915_WRITE(HSW_PWR_WELL_DRIVER, 0);
|
||||
POSTING_READ(HSW_PWR_WELL_DRIVER);
|
||||
DRM_DEBUG_KMS("Requesting to disable the power well\n");
|
||||
|
||||
/*
|
||||
* 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);
|
||||
hsw_power_well_post_disable(dev_priv);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -5748,17 +5791,26 @@ static void hsw_set_power_well(struct drm_device *dev,
|
|||
static void __intel_power_well_get(struct drm_device *dev,
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
static void __intel_power_well_put(struct drm_device *dev,
|
||||
struct i915_power_well *power_well)
|
||||
{
|
||||
struct drm_i915_private *dev_priv = dev->dev_private;
|
||||
|
||||
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);
|
||||
hsw_enable_package_c8(dev_priv);
|
||||
}
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
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 */
|
||||
void intel_init_pm(struct drm_device *dev)
|
||||
{
|
||||
struct drm_i915_private *dev_priv = dev->dev_private;
|
||||
|
||||
if (I915_HAS_FBC(dev)) {
|
||||
if (HAS_PCH_SPLIT(dev)) {
|
||||
if (INTEL_INFO(dev)->gen >= 7) {
|
||||
dev_priv->display.fbc_enabled = ironlake_fbc_enabled;
|
||||
if (IS_IVYBRIDGE(dev) || IS_HASWELL(dev))
|
||||
dev_priv->display.enable_fbc =
|
||||
gen7_enable_fbc;
|
||||
else
|
||||
dev_priv->display.enable_fbc =
|
||||
ironlake_enable_fbc;
|
||||
dev_priv->display.enable_fbc = gen7_enable_fbc;
|
||||
dev_priv->display.disable_fbc = ironlake_disable_fbc;
|
||||
} else if (INTEL_INFO(dev)->gen >= 5) {
|
||||
dev_priv->display.fbc_enabled = ironlake_fbc_enabled;
|
||||
dev_priv->display.enable_fbc = ironlake_enable_fbc;
|
||||
dev_priv->display.disable_fbc = ironlake_disable_fbc;
|
||||
} else if (IS_GM45(dev)) {
|
||||
dev_priv->display.fbc_enabled = g4x_fbc_enabled;
|
||||
dev_priv->display.enable_fbc = g4x_enable_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.enable_fbc = i8xx_enable_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 */
|
||||
|
|
|
@ -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,
|
||||
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 hbuf_size, tmp[8];
|
||||
|
|
|
@ -59,7 +59,7 @@ struct intel_sdvo_caps {
|
|||
unsigned int stall_support:1;
|
||||
unsigned int pad:1;
|
||||
u16 output_flags;
|
||||
} __attribute__((packed));
|
||||
} __packed;
|
||||
|
||||
/* Note: SDVO detailed timing flags match EDID misc flags. */
|
||||
#define DTD_FLAG_HSYNC_POSITIVE (1 << 1)
|
||||
|
@ -94,12 +94,12 @@ struct intel_sdvo_dtd {
|
|||
u8 v_sync_off_high;
|
||||
u8 reserved;
|
||||
} part2;
|
||||
} __attribute__((packed));
|
||||
} __packed;
|
||||
|
||||
struct intel_sdvo_pixel_clock_range {
|
||||
u16 min; /**< pixel clock, in 10kHz units */
|
||||
u16 max; /**< pixel clock, in 10kHz units */
|
||||
} __attribute__((packed));
|
||||
} __packed;
|
||||
|
||||
struct intel_sdvo_preferred_input_timing_args {
|
||||
u16 clock;
|
||||
|
@ -108,7 +108,7 @@ struct intel_sdvo_preferred_input_timing_args {
|
|||
u8 interlace:1;
|
||||
u8 scaled:1;
|
||||
u8 pad:6;
|
||||
} __attribute__((packed));
|
||||
} __packed;
|
||||
|
||||
/* I2C registers for SDVO */
|
||||
#define SDVO_I2C_ARG_0 0x07
|
||||
|
@ -162,7 +162,7 @@ struct intel_sdvo_get_trained_inputs_response {
|
|||
unsigned int input0_trained:1;
|
||||
unsigned int input1_trained:1;
|
||||
unsigned int pad:6;
|
||||
} __attribute__((packed));
|
||||
} __packed;
|
||||
|
||||
/** Returns a struct intel_sdvo_output_flags of active outputs. */
|
||||
#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 hdmi_audio_encrypt_change:1;
|
||||
unsigned int pad:6;
|
||||
} __attribute__((packed));
|
||||
} __packed;
|
||||
|
||||
/**
|
||||
* 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 {
|
||||
unsigned int target_1:1;
|
||||
unsigned int pad:7;
|
||||
} __attribute__((packed));
|
||||
} __packed;
|
||||
|
||||
/**
|
||||
* 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_480p_60:1;
|
||||
unsigned int pad:3;
|
||||
} __attribute__((packed));
|
||||
} __packed;
|
||||
|
||||
#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_60:1;
|
||||
unsigned int pad:5;
|
||||
} __attribute__((packed));
|
||||
} __packed;
|
||||
|
||||
struct intel_sdvo_sdtv_resolution_reply {
|
||||
unsigned int res_320x200:1;
|
||||
|
@ -426,7 +426,7 @@ struct intel_sdvo_sdtv_resolution_reply {
|
|||
unsigned int res_1024x768:1;
|
||||
unsigned int res_1280x1024:1;
|
||||
unsigned int pad:5;
|
||||
} __attribute__((packed));
|
||||
} __packed;
|
||||
|
||||
/* Get supported resolution with squire pixel aspect ratio that can be
|
||||
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_480p_60:1;
|
||||
unsigned int pad:6;
|
||||
} __attribute__((packed));
|
||||
} __packed;
|
||||
|
||||
struct intel_sdvo_hdtv_resolution_reply {
|
||||
unsigned int res_640x480:1;
|
||||
|
@ -517,7 +517,7 @@ struct intel_sdvo_hdtv_resolution_reply {
|
|||
|
||||
unsigned int res_1280x768:1;
|
||||
unsigned int pad5:7;
|
||||
} __attribute__((packed));
|
||||
} __packed;
|
||||
|
||||
/* Get supported power state returns info for encoder and monitor, rely on
|
||||
last SetTargetInput and SetTargetOutput calls */
|
||||
|
@ -557,13 +557,13 @@ struct sdvo_panel_power_sequencing {
|
|||
|
||||
unsigned int t4_high:2;
|
||||
unsigned int pad:6;
|
||||
} __attribute__((packed));
|
||||
} __packed;
|
||||
|
||||
#define SDVO_CMD_GET_MAX_BACKLIGHT_LEVEL 0x30
|
||||
struct sdvo_max_backlight_reply {
|
||||
u8 max_value;
|
||||
u8 default_value;
|
||||
} __attribute__((packed));
|
||||
} __packed;
|
||||
|
||||
#define SDVO_CMD_GET_BACKLIGHT_LEVEL 0x31
|
||||
#define SDVO_CMD_SET_BACKLIGHT_LEVEL 0x32
|
||||
|
@ -573,14 +573,14 @@ struct sdvo_get_ambient_light_reply {
|
|||
u16 trip_low;
|
||||
u16 trip_high;
|
||||
u16 value;
|
||||
} __attribute__((packed));
|
||||
} __packed;
|
||||
#define SDVO_CMD_SET_AMBIENT_LIGHT 0x34
|
||||
struct sdvo_set_ambient_light_reply {
|
||||
u16 trip_low;
|
||||
u16 trip_high;
|
||||
unsigned int enable:1;
|
||||
unsigned int pad:7;
|
||||
} __attribute__((packed));
|
||||
} __packed;
|
||||
|
||||
/* Set display power state */
|
||||
#define SDVO_CMD_SET_DISPLAY_POWER_STATE 0x7d
|
||||
|
@ -608,7 +608,7 @@ struct intel_sdvo_enhancements_reply {
|
|||
unsigned int dither:1;
|
||||
unsigned int tv_chroma_filter:1;
|
||||
unsigned int tv_luma_filter:1;
|
||||
} __attribute__((packed));
|
||||
} __packed;
|
||||
|
||||
/* Picture enhancement limits below are dependent on the current TV format,
|
||||
* 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 {
|
||||
u16 max_value;
|
||||
u16 default_value;
|
||||
} __attribute__((packed));
|
||||
} __packed;
|
||||
|
||||
#define SDVO_CMD_GET_LVDS_PANEL_INFORMATION 0x7f
|
||||
#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
|
||||
struct intel_sdvo_enhancements_arg {
|
||||
u16 value;
|
||||
} __attribute__((packed));
|
||||
} __packed;
|
||||
|
||||
#define SDVO_CMD_GET_DOT_CRAWL 0x70
|
||||
#define SDVO_CMD_SET_DOT_CRAWL 0x71
|
||||
|
@ -727,4 +727,4 @@ struct intel_sdvo_enhancements_arg {
|
|||
struct intel_sdvo_encode {
|
||||
u8 dvi_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;
|
||||
}
|
||||
}
|
||||
|
||||
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;
|
||||
|
||||
/* 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) {
|
||||
int loop = 500;
|
||||
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);
|
||||
}
|
||||
|
||||
/* 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);
|
||||
}
|
||||
|
||||
|
@ -333,8 +345,6 @@ void intel_uncore_sanitize(struct drm_device *dev)
|
|||
struct drm_i915_private *dev_priv = dev->dev_private;
|
||||
u32 reg_val;
|
||||
|
||||
intel_uncore_forcewake_reset(dev);
|
||||
|
||||
/* BIOS often leaves RC6 enabled, but disable it for hw init */
|
||||
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)
|
||||
return;
|
||||
|
||||
intel_runtime_pm_get(dev_priv);
|
||||
|
||||
/* Redirect to VLV specific routine */
|
||||
if (IS_VALLEYVIEW(dev_priv->dev))
|
||||
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);
|
||||
}
|
||||
spin_unlock_irqrestore(&dev_priv->uncore.lock, irqflags);
|
||||
|
||||
intel_runtime_pm_put(dev_priv);
|
||||
}
|
||||
|
||||
/* 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) \
|
||||
unsigned long irqflags; \
|
||||
u##x val = 0; \
|
||||
|
@ -535,12 +556,15 @@ __gen4_read(64)
|
|||
trace_i915_reg_rw(true, reg, val, sizeof(val), trace); \
|
||||
spin_lock_irqsave(&dev_priv->uncore.lock, irqflags)
|
||||
|
||||
#define REG_WRITE_FOOTER \
|
||||
spin_unlock_irqrestore(&dev_priv->uncore.lock, irqflags)
|
||||
|
||||
#define __gen4_write(x) \
|
||||
static void \
|
||||
gen4_write##x(struct drm_i915_private *dev_priv, off_t reg, u##x val, bool trace) { \
|
||||
REG_WRITE_HEADER; \
|
||||
__raw_i915_write##x(dev_priv, reg, val); \
|
||||
spin_unlock_irqrestore(&dev_priv->uncore.lock, irqflags); \
|
||||
REG_WRITE_FOOTER; \
|
||||
}
|
||||
|
||||
#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; \
|
||||
ilk_dummy_write(dev_priv); \
|
||||
__raw_i915_write##x(dev_priv, reg, val); \
|
||||
spin_unlock_irqrestore(&dev_priv->uncore.lock, irqflags); \
|
||||
REG_WRITE_FOOTER; \
|
||||
}
|
||||
|
||||
#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))) { \
|
||||
__fifo_ret = __gen6_gt_wait_for_fifo(dev_priv); \
|
||||
} \
|
||||
assert_device_not_suspended(dev_priv); \
|
||||
__raw_i915_write##x(dev_priv, reg, val); \
|
||||
if (unlikely(__fifo_ret)) { \
|
||||
gen6_gt_check_fifodbg(dev_priv); \
|
||||
} \
|
||||
spin_unlock_irqrestore(&dev_priv->uncore.lock, irqflags); \
|
||||
REG_WRITE_FOOTER; \
|
||||
}
|
||||
|
||||
#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))) { \
|
||||
__fifo_ret = __gen6_gt_wait_for_fifo(dev_priv); \
|
||||
} \
|
||||
assert_device_not_suspended(dev_priv); \
|
||||
hsw_unclaimed_reg_clear(dev_priv, reg); \
|
||||
__raw_i915_write##x(dev_priv, reg, val); \
|
||||
if (unlikely(__fifo_ret)) { \
|
||||
gen6_gt_check_fifodbg(dev_priv); \
|
||||
} \
|
||||
hsw_unclaimed_reg_check(dev_priv, reg); \
|
||||
spin_unlock_irqrestore(&dev_priv->uncore.lock, irqflags); \
|
||||
REG_WRITE_FOOTER; \
|
||||
}
|
||||
|
||||
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) \
|
||||
static void \
|
||||
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; \
|
||||
if (__needs_put) { \
|
||||
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, \
|
||||
FORCEWAKE_ALL); \
|
||||
} \
|
||||
spin_unlock_irqrestore(&dev_priv->uncore.lock, irqflags); \
|
||||
REG_WRITE_FOOTER; \
|
||||
}
|
||||
|
||||
__gen8_write(8)
|
||||
|
@ -648,6 +674,7 @@ __gen4_write(64)
|
|||
#undef __gen6_write
|
||||
#undef __gen5_write
|
||||
#undef __gen4_write
|
||||
#undef REG_WRITE_FOOTER
|
||||
#undef REG_WRITE_HEADER
|
||||
|
||||
void intel_uncore_init(struct drm_device *dev)
|
||||
|
|
Loading…
Reference in a new issue