mirror of
https://github.com/torvalds/linux.git
synced 2024-11-16 09:02:00 +00:00
Merge tag 'drm-intel-next-2015-01-17' of git://anongit.freedesktop.org/drm-intel into drm-next
- refactor i915/snd-hda interaction to use the component framework (Imre) - psr cleanups and small fixes (Rodrigo) - a few perf w/a from Ken Graunke - switch to atomic plane helpers (Matt Roper) - wc mmap support (Chris Wilson & Akash Goel) - smaller things all over * tag 'drm-intel-next-2015-01-17' of git://anongit.freedesktop.org/drm-intel: (40 commits) drm/i915: Update DRIVER_DATE to 20150117 i915: reuse %ph to dump small buffers drm/i915: Ensure the HiZ RAW Stall Optimization is on for Cherryview. drm/i915: Enable the HiZ RAW Stall Optimization on Broadwell. drm/i915: PSR link standby at debugfs drm/i915: group link_standby setup and let this info visible everywhere. drm/i915: Add missing vbt check. drm/i915: PSR HSW/BDW: Fix inverted logic at sink main_link_active bit. drm/i915: PSR VLV/CHV: Remove condition checks that only applies to Haswell. drm/i915: VLV/CHV PSR needs to exit PSR on every flush. drm/i915: Fix kerneldoc for i915 atomic plane code drm/i915: Don't pretend SDVO hotplug works on 915 drm/i915: Don't register HDMI connectors for eDP ports on VLV/CHV drm/i915: Remove I915_HAS_HOTPLUG() check from i915_hpd_irq_setup() drm/i915: Make hpd arrays big enough to avoid out of bounds access Revert "drm/i915/chv: Use timeout mode for RC6 on chv" drm/i915: Improve HiZ throughput on Cherryview. drm/i915: Reset CSB read pointer in ring init drm/i915: Drop unused position fields (v2) drm/i915: Move to atomic plane helpers (v9) ...
This commit is contained in:
commit
d3e7a0dabd
@ -4017,6 +4017,11 @@ int num_ioctls;</synopsis>
|
||||
framebuffer compression and panel self refresh.
|
||||
</para>
|
||||
</sect2>
|
||||
<sect2>
|
||||
<title>Atomic Plane Helpers</title>
|
||||
!Pdrivers/gpu/drm/i915/intel_atomic_plane.c atomic plane helpers
|
||||
!Idrivers/gpu/drm/i915/intel_atomic_plane.c
|
||||
</sect2>
|
||||
<sect2>
|
||||
<title>Output Probing</title>
|
||||
<para>
|
||||
@ -4159,6 +4164,17 @@ int num_ioctls;</synopsis>
|
||||
!Pdrivers/gpu/drm/i915/i915_gem_gtt.c Global GTT views
|
||||
!Idrivers/gpu/drm/i915/i915_gem_gtt.c
|
||||
</sect2>
|
||||
<sect2>
|
||||
<title>Buffer Object Eviction</title>
|
||||
<para>
|
||||
This section documents the interface function for evicting buffer
|
||||
objects to make space available in the virtual gpu address spaces.
|
||||
Note that this is mostly orthogonal to shrinking buffer objects
|
||||
caches, which has the goal to make main memory (shared with the gpu
|
||||
through the unified memory architecture) available.
|
||||
</para>
|
||||
!Idrivers/gpu/drm/i915/i915_gem_evict.c
|
||||
</sect2>
|
||||
</sect1>
|
||||
|
||||
<sect1>
|
||||
|
@ -66,6 +66,7 @@ i915-y += dvo_ch7017.o \
|
||||
dvo_ns2501.o \
|
||||
dvo_sil164.o \
|
||||
dvo_tfp410.o \
|
||||
intel_atomic_plane.o \
|
||||
intel_crt.o \
|
||||
intel_ddi.o \
|
||||
intel_dp.o \
|
||||
|
@ -2248,6 +2248,9 @@ static int i915_edp_psr_status(struct seq_file *m, void *data)
|
||||
}
|
||||
seq_puts(m, "\n");
|
||||
|
||||
seq_printf(m, "Link standby: %s\n",
|
||||
yesno((bool)dev_priv->psr.link_standby));
|
||||
|
||||
/* CHV PSR has no kind of performance counter */
|
||||
if (HAS_PSR(dev) && HAS_DDI(dev)) {
|
||||
psrperf = I915_READ(EDP_PSR_PERF_CNT(dev)) &
|
||||
|
@ -143,6 +143,9 @@ static int i915_getparam(struct drm_device *dev, void *data,
|
||||
case I915_PARAM_HAS_COHERENT_PHYS_GTT:
|
||||
value = 1;
|
||||
break;
|
||||
case I915_PARAM_MMAP_VERSION:
|
||||
value = 1;
|
||||
break;
|
||||
default:
|
||||
DRM_DEBUG("Unknown parameter %d\n", param->param);
|
||||
return -EINVAL;
|
||||
@ -830,6 +833,8 @@ int i915_driver_load(struct drm_device *dev, unsigned long flags)
|
||||
|
||||
intel_runtime_pm_enable(dev_priv);
|
||||
|
||||
i915_audio_component_init(dev_priv);
|
||||
|
||||
return 0;
|
||||
|
||||
out_power_well:
|
||||
@ -870,6 +875,8 @@ int i915_driver_unload(struct drm_device *dev)
|
||||
struct drm_i915_private *dev_priv = dev->dev_private;
|
||||
int ret;
|
||||
|
||||
i915_audio_component_cleanup(dev_priv);
|
||||
|
||||
ret = i915_gem_suspend(dev);
|
||||
if (ret) {
|
||||
DRM_ERROR("failed to idle hardware: %d\n", ret);
|
||||
@ -1063,6 +1070,8 @@ const struct drm_ioctl_desc i915_ioctls[] = {
|
||||
DRM_IOCTL_DEF_DRV(I915_REG_READ, i915_reg_read_ioctl, DRM_UNLOCKED|DRM_RENDER_ALLOW),
|
||||
DRM_IOCTL_DEF_DRV(I915_GET_RESET_STATS, i915_get_reset_stats_ioctl, DRM_UNLOCKED|DRM_RENDER_ALLOW),
|
||||
DRM_IOCTL_DEF_DRV(I915_GEM_USERPTR, i915_gem_userptr_ioctl, DRM_UNLOCKED|DRM_RENDER_ALLOW),
|
||||
DRM_IOCTL_DEF_DRV(I915_GEM_CONTEXT_GETPARAM, i915_gem_context_getparam_ioctl, DRM_UNLOCKED|DRM_RENDER_ALLOW),
|
||||
DRM_IOCTL_DEF_DRV(I915_GEM_CONTEXT_SETPARAM, i915_gem_context_setparam_ioctl, DRM_UNLOCKED|DRM_RENDER_ALLOW),
|
||||
};
|
||||
|
||||
int i915_max_ioctl = ARRAY_SIZE(i915_ioctls);
|
||||
|
@ -942,8 +942,7 @@ static int i915_pm_suspend(struct device *dev)
|
||||
|
||||
static int i915_pm_suspend_late(struct device *dev)
|
||||
{
|
||||
struct pci_dev *pdev = to_pci_dev(dev);
|
||||
struct drm_device *drm_dev = pci_get_drvdata(pdev);
|
||||
struct drm_device *drm_dev = dev_to_i915(dev)->dev;
|
||||
|
||||
/*
|
||||
* We have a suspedn ordering issue with the snd-hda driver also
|
||||
@ -962,8 +961,7 @@ static int i915_pm_suspend_late(struct device *dev)
|
||||
|
||||
static int i915_pm_resume_early(struct device *dev)
|
||||
{
|
||||
struct pci_dev *pdev = to_pci_dev(dev);
|
||||
struct drm_device *drm_dev = pci_get_drvdata(pdev);
|
||||
struct drm_device *drm_dev = dev_to_i915(dev)->dev;
|
||||
|
||||
if (drm_dev->switch_power_state == DRM_SWITCH_POWER_OFF)
|
||||
return 0;
|
||||
@ -973,8 +971,7 @@ static int i915_pm_resume_early(struct device *dev)
|
||||
|
||||
static int i915_pm_resume(struct device *dev)
|
||||
{
|
||||
struct pci_dev *pdev = to_pci_dev(dev);
|
||||
struct drm_device *drm_dev = pci_get_drvdata(pdev);
|
||||
struct drm_device *drm_dev = dev_to_i915(dev)->dev;
|
||||
|
||||
if (drm_dev->switch_power_state == DRM_SWITCH_POWER_OFF)
|
||||
return 0;
|
||||
|
@ -55,7 +55,7 @@
|
||||
|
||||
#define DRIVER_NAME "i915"
|
||||
#define DRIVER_DESC "Intel Graphics"
|
||||
#define DRIVER_DATE "20141219"
|
||||
#define DRIVER_DATE "20150117"
|
||||
|
||||
#undef WARN_ON
|
||||
/* Many gcc seem to no see through this and fall over :( */
|
||||
@ -83,7 +83,7 @@
|
||||
int __ret_warn_on = !!(condition); \
|
||||
if (unlikely(__ret_warn_on)) { \
|
||||
if (i915.verbose_state_checks) \
|
||||
__WARN_printf(format); \
|
||||
WARN(1, format); \
|
||||
else \
|
||||
DRM_ERROR(format); \
|
||||
} \
|
||||
@ -94,7 +94,7 @@
|
||||
int __ret_warn_on = !!(condition); \
|
||||
if (unlikely(__ret_warn_on)) { \
|
||||
if (i915.verbose_state_checks) \
|
||||
__WARN_printf("WARN_ON(" #condition ")\n"); \
|
||||
WARN(1, "WARN_ON(" #condition ")\n"); \
|
||||
else \
|
||||
DRM_ERROR("WARN_ON(" #condition ")\n"); \
|
||||
} \
|
||||
@ -678,6 +678,11 @@ struct i915_ctx_hang_stats {
|
||||
/* Time when this context was last blamed for a GPU reset */
|
||||
unsigned long guilty_ts;
|
||||
|
||||
/* If the contexts causes a second GPU hang within this time,
|
||||
* it is permanently banned from submitting any more work.
|
||||
*/
|
||||
unsigned long ban_period_seconds;
|
||||
|
||||
/* This context is banned to submit more work */
|
||||
bool banned;
|
||||
};
|
||||
@ -784,6 +789,7 @@ struct i915_psr {
|
||||
bool active;
|
||||
struct delayed_work work;
|
||||
unsigned busy_frontbuffer_bits;
|
||||
bool link_standby;
|
||||
};
|
||||
|
||||
enum intel_pch {
|
||||
@ -1409,7 +1415,6 @@ struct intel_vbt_data {
|
||||
bool present;
|
||||
bool active_low_pwm;
|
||||
u8 min_brightness; /* min_brightness/255 of max */
|
||||
u8 controller; /* brightness controller number */
|
||||
} backlight;
|
||||
|
||||
/* MIPI DSI */
|
||||
@ -1768,6 +1773,9 @@ struct drm_i915_private {
|
||||
struct drm_property *broadcast_rgb_property;
|
||||
struct drm_property *force_audio_property;
|
||||
|
||||
/* hda/i915 audio component */
|
||||
bool audio_component_registered;
|
||||
|
||||
uint32_t hw_context_size;
|
||||
struct list_head context_list;
|
||||
|
||||
@ -1853,6 +1861,11 @@ static inline struct drm_i915_private *to_i915(const struct drm_device *dev)
|
||||
return dev->dev_private;
|
||||
}
|
||||
|
||||
static inline struct drm_i915_private *dev_to_i915(struct device *dev)
|
||||
{
|
||||
return to_i915(dev_get_drvdata(dev));
|
||||
}
|
||||
|
||||
/* Iterate over initialised rings */
|
||||
#define for_each_ring(ring__, dev_priv__, i__) \
|
||||
for ((i__) = 0; (i__) < I915_NUM_RINGS; (i__)++) \
|
||||
@ -2892,6 +2905,10 @@ int i915_gem_context_create_ioctl(struct drm_device *dev, void *data,
|
||||
struct drm_file *file);
|
||||
int i915_gem_context_destroy_ioctl(struct drm_device *dev, void *data,
|
||||
struct drm_file *file);
|
||||
int i915_gem_context_getparam_ioctl(struct drm_device *dev, void *data,
|
||||
struct drm_file *file_priv);
|
||||
int i915_gem_context_setparam_ioctl(struct drm_device *dev, void *data,
|
||||
struct drm_file *file_priv);
|
||||
|
||||
/* i915_gem_evict.c */
|
||||
int __must_check i915_gem_evict_something(struct drm_device *dev,
|
||||
|
@ -153,12 +153,6 @@ int i915_mutex_lock_interruptible(struct drm_device *dev)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static inline bool
|
||||
i915_gem_object_is_inactive(struct drm_i915_gem_object *obj)
|
||||
{
|
||||
return i915_gem_obj_bound_any(obj) && !obj->active;
|
||||
}
|
||||
|
||||
int
|
||||
i915_gem_get_aperture_ioctl(struct drm_device *dev, void *data,
|
||||
struct drm_file *file)
|
||||
@ -1487,18 +1481,10 @@ i915_gem_set_domain_ioctl(struct drm_device *dev, void *data,
|
||||
if (ret)
|
||||
goto unref;
|
||||
|
||||
if (read_domains & I915_GEM_DOMAIN_GTT) {
|
||||
if (read_domains & I915_GEM_DOMAIN_GTT)
|
||||
ret = i915_gem_object_set_to_gtt_domain(obj, write_domain != 0);
|
||||
|
||||
/* Silently promote "you're not bound, there was nothing to do"
|
||||
* to success, since the client was just asking us to
|
||||
* make sure everything was done.
|
||||
*/
|
||||
if (ret == -EINVAL)
|
||||
ret = 0;
|
||||
} else {
|
||||
else
|
||||
ret = i915_gem_object_set_to_cpu_domain(obj, write_domain != 0);
|
||||
}
|
||||
|
||||
unref:
|
||||
drm_gem_object_unreference(&obj->base);
|
||||
@ -1563,6 +1549,12 @@ i915_gem_mmap_ioctl(struct drm_device *dev, void *data,
|
||||
struct drm_gem_object *obj;
|
||||
unsigned long addr;
|
||||
|
||||
if (args->flags & ~(I915_MMAP_WC))
|
||||
return -EINVAL;
|
||||
|
||||
if (args->flags & I915_MMAP_WC && !cpu_has_pat)
|
||||
return -ENODEV;
|
||||
|
||||
obj = drm_gem_object_lookup(dev, file, args->handle);
|
||||
if (obj == NULL)
|
||||
return -ENOENT;
|
||||
@ -1578,6 +1570,19 @@ i915_gem_mmap_ioctl(struct drm_device *dev, void *data,
|
||||
addr = vm_mmap(obj->filp, 0, args->size,
|
||||
PROT_READ | PROT_WRITE, MAP_SHARED,
|
||||
args->offset);
|
||||
if (args->flags & I915_MMAP_WC) {
|
||||
struct mm_struct *mm = current->mm;
|
||||
struct vm_area_struct *vma;
|
||||
|
||||
down_write(&mm->mmap_sem);
|
||||
vma = find_vma(mm, addr);
|
||||
if (vma)
|
||||
vma->vm_page_prot =
|
||||
pgprot_writecombine(vm_get_page_prot(vma->vm_flags));
|
||||
else
|
||||
addr = -ENOMEM;
|
||||
up_write(&mm->mmap_sem);
|
||||
}
|
||||
drm_gem_object_unreference_unlocked(obj);
|
||||
if (IS_ERR((void *)addr))
|
||||
return addr;
|
||||
@ -2529,7 +2534,8 @@ static bool i915_context_is_banned(struct drm_i915_private *dev_priv,
|
||||
if (ctx->hang_stats.banned)
|
||||
return true;
|
||||
|
||||
if (elapsed <= DRM_I915_CTX_BAN_PERIOD) {
|
||||
if (ctx->hang_stats.ban_period_seconds &&
|
||||
elapsed <= ctx->hang_stats.ban_period_seconds) {
|
||||
if (!i915_gem_context_is_default(ctx)) {
|
||||
DRM_DEBUG("context hanging too fast, banning!\n");
|
||||
return true;
|
||||
@ -3698,15 +3704,10 @@ i915_gem_object_flush_cpu_write_domain(struct drm_i915_gem_object *obj,
|
||||
int
|
||||
i915_gem_object_set_to_gtt_domain(struct drm_i915_gem_object *obj, bool write)
|
||||
{
|
||||
struct drm_i915_private *dev_priv = obj->base.dev->dev_private;
|
||||
struct i915_vma *vma = i915_gem_obj_to_ggtt(obj);
|
||||
uint32_t old_write_domain, old_read_domains;
|
||||
struct i915_vma *vma;
|
||||
int ret;
|
||||
|
||||
/* Not valid to be called on unbound objects. */
|
||||
if (vma == NULL)
|
||||
return -EINVAL;
|
||||
|
||||
if (obj->base.write_domain == I915_GEM_DOMAIN_GTT)
|
||||
return 0;
|
||||
|
||||
@ -3715,6 +3716,19 @@ i915_gem_object_set_to_gtt_domain(struct drm_i915_gem_object *obj, bool write)
|
||||
return ret;
|
||||
|
||||
i915_gem_object_retire(obj);
|
||||
|
||||
/* Flush and acquire obj->pages so that we are coherent through
|
||||
* direct access in memory with previous cached writes through
|
||||
* shmemfs and that our cache domain tracking remains valid.
|
||||
* For example, if the obj->filp was moved to swap without us
|
||||
* being notified and releasing the pages, we would mistakenly
|
||||
* continue to assume that the obj remained out of the CPU cached
|
||||
* domain.
|
||||
*/
|
||||
ret = i915_gem_object_get_pages(obj);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
i915_gem_object_flush_cpu_write_domain(obj, false);
|
||||
|
||||
/* Serialise direct access to this object with the barriers for
|
||||
@ -3746,9 +3760,10 @@ i915_gem_object_set_to_gtt_domain(struct drm_i915_gem_object *obj, bool write)
|
||||
old_write_domain);
|
||||
|
||||
/* And bump the LRU for this access */
|
||||
if (i915_gem_object_is_inactive(obj))
|
||||
vma = i915_gem_obj_to_ggtt(obj);
|
||||
if (vma && drm_mm_node_allocated(&vma->node) && !obj->active)
|
||||
list_move_tail(&vma->mm_list,
|
||||
&dev_priv->gtt.base.inactive_list);
|
||||
&to_i915(obj->base.dev)->gtt.base.inactive_list);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -222,6 +222,8 @@ __create_hw_context(struct drm_device *dev,
|
||||
* is no remap info, it will be a NOP. */
|
||||
ctx->remap_slice = (1 << NUM_L3_SLICES(dev)) - 1;
|
||||
|
||||
ctx->hang_stats.ban_period_seconds = DRM_I915_CTX_BAN_PERIOD;
|
||||
|
||||
return ctx;
|
||||
|
||||
err_out:
|
||||
@ -792,3 +794,72 @@ int i915_gem_context_destroy_ioctl(struct drm_device *dev, void *data,
|
||||
DRM_DEBUG_DRIVER("HW context %d destroyed\n", args->ctx_id);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int i915_gem_context_getparam_ioctl(struct drm_device *dev, void *data,
|
||||
struct drm_file *file)
|
||||
{
|
||||
struct drm_i915_file_private *file_priv = file->driver_priv;
|
||||
struct drm_i915_gem_context_param *args = data;
|
||||
struct intel_context *ctx;
|
||||
int ret;
|
||||
|
||||
ret = i915_mutex_lock_interruptible(dev);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
ctx = i915_gem_context_get(file_priv, args->ctx_id);
|
||||
if (IS_ERR(ctx)) {
|
||||
mutex_unlock(&dev->struct_mutex);
|
||||
return PTR_ERR(ctx);
|
||||
}
|
||||
|
||||
args->size = 0;
|
||||
switch (args->param) {
|
||||
case I915_CONTEXT_PARAM_BAN_PERIOD:
|
||||
args->value = ctx->hang_stats.ban_period_seconds;
|
||||
break;
|
||||
default:
|
||||
ret = -EINVAL;
|
||||
break;
|
||||
}
|
||||
mutex_unlock(&dev->struct_mutex);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
int i915_gem_context_setparam_ioctl(struct drm_device *dev, void *data,
|
||||
struct drm_file *file)
|
||||
{
|
||||
struct drm_i915_file_private *file_priv = file->driver_priv;
|
||||
struct drm_i915_gem_context_param *args = data;
|
||||
struct intel_context *ctx;
|
||||
int ret;
|
||||
|
||||
ret = i915_mutex_lock_interruptible(dev);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
ctx = i915_gem_context_get(file_priv, args->ctx_id);
|
||||
if (IS_ERR(ctx)) {
|
||||
mutex_unlock(&dev->struct_mutex);
|
||||
return PTR_ERR(ctx);
|
||||
}
|
||||
|
||||
switch (args->param) {
|
||||
case I915_CONTEXT_PARAM_BAN_PERIOD:
|
||||
if (args->size)
|
||||
ret = -EINVAL;
|
||||
else if (args->value < ctx->hang_stats.ban_period_seconds &&
|
||||
!capable(CAP_SYS_ADMIN))
|
||||
ret = -EPERM;
|
||||
else
|
||||
ctx->hang_stats.ban_period_seconds = args->value;
|
||||
break;
|
||||
default:
|
||||
ret = -EINVAL;
|
||||
break;
|
||||
}
|
||||
mutex_unlock(&dev->struct_mutex);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
@ -50,11 +50,12 @@ mark_free(struct i915_vma *vma, struct list_head *unwind)
|
||||
* i915_gem_evict_something - Evict vmas to make room for binding a new one
|
||||
* @dev: drm_device
|
||||
* @vm: address space to evict from
|
||||
* @size: size of the desired free space
|
||||
* @min_size: size of the desired free space
|
||||
* @alignment: alignment constraint of the desired free space
|
||||
* @cache_level: cache_level for the desired space
|
||||
* @mappable: whether the free space must be mappable
|
||||
* @nonblocking: whether evicting active objects is allowed or not
|
||||
* @start: start (inclusive) of the range from which to evict objects
|
||||
* @end: end (exclusive) of the range from which to evict objects
|
||||
* @flags: additional flags to control the eviction algorithm
|
||||
*
|
||||
* This function will try to evict vmas until a free space satisfying the
|
||||
* requirements is found. Callers must check first whether any such hole exists
|
||||
@ -196,7 +197,6 @@ found:
|
||||
|
||||
/**
|
||||
* i915_gem_evict_vm - Evict all idle vmas from a vm
|
||||
*
|
||||
* @vm: Address space to cleanse
|
||||
* @do_idle: Boolean directing whether to idle first.
|
||||
*
|
||||
@ -214,6 +214,7 @@ int i915_gem_evict_vm(struct i915_address_space *vm, bool do_idle)
|
||||
struct i915_vma *vma, *next;
|
||||
int ret;
|
||||
|
||||
WARN_ON(!mutex_is_locked(&vm->dev->struct_mutex));
|
||||
trace_i915_gem_evict_vm(vm);
|
||||
|
||||
if (do_idle) {
|
||||
@ -222,6 +223,8 @@ int i915_gem_evict_vm(struct i915_address_space *vm, bool do_idle)
|
||||
return ret;
|
||||
|
||||
i915_gem_retire_requests(vm->dev);
|
||||
|
||||
WARN_ON(!list_empty(&vm->active_list));
|
||||
}
|
||||
|
||||
list_for_each_entry_safe(vma, next, &vm->inactive_list, mm_list)
|
||||
|
@ -1081,6 +1081,7 @@ i915_gem_execbuffer_parse(struct intel_engine_cs *ring,
|
||||
{
|
||||
struct drm_i915_private *dev_priv = to_i915(batch_obj->base.dev);
|
||||
struct drm_i915_gem_object *shadow_batch_obj;
|
||||
bool need_reloc = false;
|
||||
int ret;
|
||||
|
||||
shadow_batch_obj = i915_gem_batch_pool_get(&dev_priv->mm.batch_pool,
|
||||
@ -1106,6 +1107,7 @@ i915_gem_execbuffer_parse(struct intel_engine_cs *ring,
|
||||
vma->exec_entry = shadow_exec_entry;
|
||||
vma->exec_entry->flags = __EXEC_OBJECT_PURGEABLE;
|
||||
drm_gem_object_reference(&shadow_batch_obj->base);
|
||||
i915_gem_execbuffer_reserve_vma(vma, ring, &need_reloc);
|
||||
list_add_tail(&vma->exec_list, &eb->vmas);
|
||||
|
||||
shadow_batch_obj->base.pending_read_domains =
|
||||
|
@ -45,7 +45,7 @@
|
||||
* and related files, but that will be described in separate chapters.
|
||||
*/
|
||||
|
||||
static const u32 hpd_ibx[] = {
|
||||
static const u32 hpd_ibx[HPD_NUM_PINS] = {
|
||||
[HPD_CRT] = SDE_CRT_HOTPLUG,
|
||||
[HPD_SDVO_B] = SDE_SDVOB_HOTPLUG,
|
||||
[HPD_PORT_B] = SDE_PORTB_HOTPLUG,
|
||||
@ -53,7 +53,7 @@ static const u32 hpd_ibx[] = {
|
||||
[HPD_PORT_D] = SDE_PORTD_HOTPLUG
|
||||
};
|
||||
|
||||
static const u32 hpd_cpt[] = {
|
||||
static const u32 hpd_cpt[HPD_NUM_PINS] = {
|
||||
[HPD_CRT] = SDE_CRT_HOTPLUG_CPT,
|
||||
[HPD_SDVO_B] = SDE_SDVOB_HOTPLUG_CPT,
|
||||
[HPD_PORT_B] = SDE_PORTB_HOTPLUG_CPT,
|
||||
@ -61,7 +61,7 @@ static const u32 hpd_cpt[] = {
|
||||
[HPD_PORT_D] = SDE_PORTD_HOTPLUG_CPT
|
||||
};
|
||||
|
||||
static const u32 hpd_mask_i915[] = {
|
||||
static const u32 hpd_mask_i915[HPD_NUM_PINS] = {
|
||||
[HPD_CRT] = CRT_HOTPLUG_INT_EN,
|
||||
[HPD_SDVO_B] = SDVOB_HOTPLUG_INT_EN,
|
||||
[HPD_SDVO_C] = SDVOC_HOTPLUG_INT_EN,
|
||||
@ -70,7 +70,7 @@ static const u32 hpd_mask_i915[] = {
|
||||
[HPD_PORT_D] = PORTD_HOTPLUG_INT_EN
|
||||
};
|
||||
|
||||
static const u32 hpd_status_g4x[] = {
|
||||
static const u32 hpd_status_g4x[HPD_NUM_PINS] = {
|
||||
[HPD_CRT] = CRT_HOTPLUG_INT_STATUS,
|
||||
[HPD_SDVO_B] = SDVOB_HOTPLUG_INT_STATUS_G4X,
|
||||
[HPD_SDVO_C] = SDVOC_HOTPLUG_INT_STATUS_G4X,
|
||||
@ -79,7 +79,7 @@ static const u32 hpd_status_g4x[] = {
|
||||
[HPD_PORT_D] = PORTD_HOTPLUG_INT_STATUS
|
||||
};
|
||||
|
||||
static const u32 hpd_status_i915[] = { /* i915 and valleyview are the same */
|
||||
static const u32 hpd_status_i915[HPD_NUM_PINS] = { /* i915 and valleyview are the same */
|
||||
[HPD_CRT] = CRT_HOTPLUG_INT_STATUS,
|
||||
[HPD_SDVO_B] = SDVOB_HOTPLUG_INT_STATUS_I915,
|
||||
[HPD_SDVO_C] = SDVOC_HOTPLUG_INT_STATUS_I915,
|
||||
@ -1522,7 +1522,7 @@ static inline enum port get_port_from_pin(enum hpd_pin pin)
|
||||
static inline void intel_hpd_irq_handler(struct drm_device *dev,
|
||||
u32 hotplug_trigger,
|
||||
u32 dig_hotplug_reg,
|
||||
const u32 *hpd)
|
||||
const u32 hpd[HPD_NUM_PINS])
|
||||
{
|
||||
struct drm_i915_private *dev_priv = dev->dev_private;
|
||||
int i;
|
||||
@ -4145,26 +4145,24 @@ static void i915_hpd_irq_setup(struct drm_device *dev)
|
||||
|
||||
assert_spin_locked(&dev_priv->irq_lock);
|
||||
|
||||
if (I915_HAS_HOTPLUG(dev)) {
|
||||
hotplug_en = I915_READ(PORT_HOTPLUG_EN);
|
||||
hotplug_en &= ~HOTPLUG_INT_EN_MASK;
|
||||
/* Note HDMI and DP share hotplug bits */
|
||||
/* enable bits are the same for all generations */
|
||||
for_each_intel_encoder(dev, intel_encoder)
|
||||
if (dev_priv->hpd_stats[intel_encoder->hpd_pin].hpd_mark == HPD_ENABLED)
|
||||
hotplug_en |= hpd_mask_i915[intel_encoder->hpd_pin];
|
||||
/* Programming the CRT detection parameters tends
|
||||
to generate a spurious hotplug event about three
|
||||
seconds later. So just do it once.
|
||||
*/
|
||||
if (IS_G4X(dev))
|
||||
hotplug_en |= CRT_HOTPLUG_ACTIVATION_PERIOD_64;
|
||||
hotplug_en &= ~CRT_HOTPLUG_VOLTAGE_COMPARE_MASK;
|
||||
hotplug_en |= CRT_HOTPLUG_VOLTAGE_COMPARE_50;
|
||||
hotplug_en = I915_READ(PORT_HOTPLUG_EN);
|
||||
hotplug_en &= ~HOTPLUG_INT_EN_MASK;
|
||||
/* Note HDMI and DP share hotplug bits */
|
||||
/* enable bits are the same for all generations */
|
||||
for_each_intel_encoder(dev, intel_encoder)
|
||||
if (dev_priv->hpd_stats[intel_encoder->hpd_pin].hpd_mark == HPD_ENABLED)
|
||||
hotplug_en |= hpd_mask_i915[intel_encoder->hpd_pin];
|
||||
/* Programming the CRT detection parameters tends
|
||||
to generate a spurious hotplug event about three
|
||||
seconds later. So just do it once.
|
||||
*/
|
||||
if (IS_G4X(dev))
|
||||
hotplug_en |= CRT_HOTPLUG_ACTIVATION_PERIOD_64;
|
||||
hotplug_en &= ~CRT_HOTPLUG_VOLTAGE_COMPARE_MASK;
|
||||
hotplug_en |= CRT_HOTPLUG_VOLTAGE_COMPARE_50;
|
||||
|
||||
/* Ignore TV since it's buggy */
|
||||
I915_WRITE(PORT_HOTPLUG_EN, hotplug_en);
|
||||
}
|
||||
/* Ignore TV since it's buggy */
|
||||
I915_WRITE(PORT_HOTPLUG_EN, hotplug_en);
|
||||
}
|
||||
|
||||
static irqreturn_t i965_irq_handler(int irq, void *arg)
|
||||
@ -4428,14 +4426,14 @@ void intel_irq_init(struct drm_i915_private *dev_priv)
|
||||
dev->driver->irq_postinstall = i915_irq_postinstall;
|
||||
dev->driver->irq_uninstall = i915_irq_uninstall;
|
||||
dev->driver->irq_handler = i915_irq_handler;
|
||||
dev_priv->display.hpd_irq_setup = i915_hpd_irq_setup;
|
||||
} else {
|
||||
dev->driver->irq_preinstall = i965_irq_preinstall;
|
||||
dev->driver->irq_postinstall = i965_irq_postinstall;
|
||||
dev->driver->irq_uninstall = i965_irq_uninstall;
|
||||
dev->driver->irq_handler = i965_irq_handler;
|
||||
dev_priv->display.hpd_irq_setup = i915_hpd_irq_setup;
|
||||
}
|
||||
if (I915_HAS_HOTPLUG(dev_priv))
|
||||
dev_priv->display.hpd_irq_setup = i915_hpd_irq_setup;
|
||||
dev->driver->enable_vblank = i915_enable_vblank;
|
||||
dev->driver->disable_vblank = i915_disable_vblank;
|
||||
}
|
||||
|
@ -5202,6 +5202,9 @@ enum punit_power_well {
|
||||
#define COMMON_SLICE_CHICKEN2 0x7014
|
||||
# define GEN8_CSC2_SBE_VUE_CACHE_CONSERVATIVE (1<<0)
|
||||
|
||||
#define HIZ_CHICKEN 0x7018
|
||||
# define CHV_HZ_8X8_MODE_IN_1X (1<<15)
|
||||
|
||||
#define GEN7_L3SQCREG1 0xB010
|
||||
#define VLV_B0_WA_L3SQCREG1_VALUE 0x00D30000
|
||||
|
||||
@ -6167,6 +6170,7 @@ enum punit_power_well {
|
||||
#define HSW_ROW_CHICKEN3_L3_GLOBAL_ATOMICS_DISABLE (1 << 6)
|
||||
|
||||
#define HALF_SLICE_CHICKEN3 0xe184
|
||||
#define HSW_SAMPLE_C_PERFORMANCE (1<<9)
|
||||
#define GEN8_CENTROID_PIXEL_OPT_DIS (1<<8)
|
||||
#define GEN8_SAMPLER_POWER_BYPASS_DIS (1<<1)
|
||||
|
||||
|
152
drivers/gpu/drm/i915/intel_atomic_plane.c
Normal file
152
drivers/gpu/drm/i915/intel_atomic_plane.c
Normal file
@ -0,0 +1,152 @@
|
||||
/*
|
||||
* Copyright © 2014 Intel Corporation
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a
|
||||
* copy of this software and associated documentation files (the "Software"),
|
||||
* to deal in the Software without restriction, including without limitation
|
||||
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||
* and/or sell copies of the Software, and to permit persons to whom the
|
||||
* Software is furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice (including the next
|
||||
* paragraph) shall be included in all copies or substantial portions of the
|
||||
* Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||||
* DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
/**
|
||||
* DOC: atomic plane helpers
|
||||
*
|
||||
* The functions here are used by the atomic plane helper functions to
|
||||
* implement legacy plane updates (i.e., drm_plane->update_plane() and
|
||||
* drm_plane->disable_plane()). This allows plane updates to use the
|
||||
* atomic state infrastructure and perform plane updates as separate
|
||||
* prepare/check/commit/cleanup steps.
|
||||
*/
|
||||
|
||||
#include <drm/drmP.h>
|
||||
#include <drm/drm_atomic_helper.h>
|
||||
#include <drm/drm_plane_helper.h>
|
||||
#include "intel_drv.h"
|
||||
|
||||
/**
|
||||
* intel_plane_duplicate_state - duplicate plane state
|
||||
* @plane: drm plane
|
||||
*
|
||||
* Allocates and returns a copy of the plane state (both common and
|
||||
* Intel-specific) for the specified plane.
|
||||
*
|
||||
* Returns: The newly allocated plane state, or NULL or failure.
|
||||
*/
|
||||
struct drm_plane_state *
|
||||
intel_plane_duplicate_state(struct drm_plane *plane)
|
||||
{
|
||||
struct intel_plane_state *state;
|
||||
|
||||
if (plane->state)
|
||||
state = kmemdup(plane->state, sizeof(*state), GFP_KERNEL);
|
||||
else
|
||||
state = kzalloc(sizeof(*state), GFP_KERNEL);
|
||||
|
||||
if (!state)
|
||||
return NULL;
|
||||
|
||||
if (state->base.fb)
|
||||
drm_framebuffer_reference(state->base.fb);
|
||||
|
||||
return &state->base;
|
||||
}
|
||||
|
||||
/**
|
||||
* intel_plane_destroy_state - destroy plane state
|
||||
* @plane: drm plane
|
||||
* @state: state object to destroy
|
||||
*
|
||||
* Destroys the plane state (both common and Intel-specific) for the
|
||||
* specified plane.
|
||||
*/
|
||||
void
|
||||
intel_plane_destroy_state(struct drm_plane *plane,
|
||||
struct drm_plane_state *state)
|
||||
{
|
||||
drm_atomic_helper_plane_destroy_state(plane, state);
|
||||
}
|
||||
|
||||
static int intel_plane_atomic_check(struct drm_plane *plane,
|
||||
struct drm_plane_state *state)
|
||||
{
|
||||
struct drm_crtc *crtc = state->crtc;
|
||||
struct intel_crtc *intel_crtc;
|
||||
struct intel_plane *intel_plane = to_intel_plane(plane);
|
||||
struct intel_plane_state *intel_state = to_intel_plane_state(state);
|
||||
|
||||
crtc = crtc ? crtc : plane->crtc;
|
||||
intel_crtc = to_intel_crtc(crtc);
|
||||
|
||||
/*
|
||||
* The original src/dest coordinates are stored in state->base, but
|
||||
* we want to keep another copy internal to our driver that we can
|
||||
* clip/modify ourselves.
|
||||
*/
|
||||
intel_state->src.x1 = state->src_x;
|
||||
intel_state->src.y1 = state->src_y;
|
||||
intel_state->src.x2 = state->src_x + state->src_w;
|
||||
intel_state->src.y2 = state->src_y + state->src_h;
|
||||
intel_state->dst.x1 = state->crtc_x;
|
||||
intel_state->dst.y1 = state->crtc_y;
|
||||
intel_state->dst.x2 = state->crtc_x + state->crtc_w;
|
||||
intel_state->dst.y2 = state->crtc_y + state->crtc_h;
|
||||
|
||||
/* Clip all planes to CRTC size, or 0x0 if CRTC is disabled */
|
||||
intel_state->clip.x1 = 0;
|
||||
intel_state->clip.y1 = 0;
|
||||
intel_state->clip.x2 =
|
||||
intel_crtc->active ? intel_crtc->config.pipe_src_w : 0;
|
||||
intel_state->clip.y2 =
|
||||
intel_crtc->active ? intel_crtc->config.pipe_src_h : 0;
|
||||
|
||||
/*
|
||||
* Disabling a plane is always okay; we just need to update
|
||||
* fb tracking in a special way since cleanup_fb() won't
|
||||
* get called by the plane helpers.
|
||||
*/
|
||||
if (state->fb == NULL && plane->state->fb != NULL) {
|
||||
/*
|
||||
* 'prepare' is never called when plane is being disabled, so
|
||||
* we need to handle frontbuffer tracking as a special case
|
||||
*/
|
||||
intel_crtc->atomic.disabled_planes |=
|
||||
(1 << drm_plane_index(plane));
|
||||
}
|
||||
|
||||
return intel_plane->check_plane(plane, intel_state);
|
||||
}
|
||||
|
||||
static void intel_plane_atomic_update(struct drm_plane *plane,
|
||||
struct drm_plane_state *old_state)
|
||||
{
|
||||
struct intel_plane *intel_plane = to_intel_plane(plane);
|
||||
struct intel_plane_state *intel_state =
|
||||
to_intel_plane_state(plane->state);
|
||||
|
||||
/* Don't disable an already disabled plane */
|
||||
if (!plane->state->fb && !old_state->fb)
|
||||
return;
|
||||
|
||||
intel_plane->commit_plane(plane, intel_state);
|
||||
}
|
||||
|
||||
const struct drm_plane_helper_funcs intel_plane_helper_funcs = {
|
||||
.prepare_fb = intel_prepare_plane_fb,
|
||||
.cleanup_fb = intel_cleanup_plane_fb,
|
||||
.atomic_check = intel_plane_atomic_check,
|
||||
.atomic_update = intel_plane_atomic_update,
|
||||
};
|
||||
|
@ -22,6 +22,9 @@
|
||||
*/
|
||||
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/component.h>
|
||||
#include <drm/i915_component.h>
|
||||
#include "intel_drv.h"
|
||||
|
||||
#include <drm/drmP.h>
|
||||
#include <drm/drm_edid.h>
|
||||
@ -461,3 +464,110 @@ void intel_init_audio(struct drm_device *dev)
|
||||
dev_priv->display.audio_codec_disable = ilk_audio_codec_disable;
|
||||
}
|
||||
}
|
||||
|
||||
static void i915_audio_component_get_power(struct device *dev)
|
||||
{
|
||||
intel_display_power_get(dev_to_i915(dev), POWER_DOMAIN_AUDIO);
|
||||
}
|
||||
|
||||
static void i915_audio_component_put_power(struct device *dev)
|
||||
{
|
||||
intel_display_power_put(dev_to_i915(dev), POWER_DOMAIN_AUDIO);
|
||||
}
|
||||
|
||||
/* Get CDCLK in kHz */
|
||||
static int i915_audio_component_get_cdclk_freq(struct device *dev)
|
||||
{
|
||||
struct drm_i915_private *dev_priv = dev_to_i915(dev);
|
||||
int ret;
|
||||
|
||||
if (WARN_ON_ONCE(!HAS_DDI(dev_priv)))
|
||||
return -ENODEV;
|
||||
|
||||
intel_display_power_get(dev_priv, POWER_DOMAIN_AUDIO);
|
||||
ret = intel_ddi_get_cdclk_freq(dev_priv);
|
||||
intel_display_power_put(dev_priv, POWER_DOMAIN_AUDIO);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static const struct i915_audio_component_ops i915_audio_component_ops = {
|
||||
.owner = THIS_MODULE,
|
||||
.get_power = i915_audio_component_get_power,
|
||||
.put_power = i915_audio_component_put_power,
|
||||
.get_cdclk_freq = i915_audio_component_get_cdclk_freq,
|
||||
};
|
||||
|
||||
static int i915_audio_component_bind(struct device *i915_dev,
|
||||
struct device *hda_dev, void *data)
|
||||
{
|
||||
struct i915_audio_component *acomp = data;
|
||||
|
||||
if (WARN_ON(acomp->ops || acomp->dev))
|
||||
return -EEXIST;
|
||||
|
||||
acomp->ops = &i915_audio_component_ops;
|
||||
acomp->dev = i915_dev;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void i915_audio_component_unbind(struct device *i915_dev,
|
||||
struct device *hda_dev, void *data)
|
||||
{
|
||||
struct i915_audio_component *acomp = data;
|
||||
|
||||
acomp->ops = NULL;
|
||||
acomp->dev = NULL;
|
||||
}
|
||||
|
||||
static const struct component_ops i915_audio_component_bind_ops = {
|
||||
.bind = i915_audio_component_bind,
|
||||
.unbind = i915_audio_component_unbind,
|
||||
};
|
||||
|
||||
/**
|
||||
* i915_audio_component_init - initialize and register the audio component
|
||||
* @dev_priv: i915 device instance
|
||||
*
|
||||
* This will register with the component framework a child component which
|
||||
* will bind dynamically to the snd_hda_intel driver's corresponding master
|
||||
* component when the latter is registered. During binding the child
|
||||
* initializes an instance of struct i915_audio_component which it receives
|
||||
* from the master. The master can then start to use the interface defined by
|
||||
* this struct. Each side can break the binding at any point by deregistering
|
||||
* its own component after which each side's component unbind callback is
|
||||
* called.
|
||||
*
|
||||
* We ignore any error during registration and continue with reduced
|
||||
* functionality (i.e. without HDMI audio).
|
||||
*/
|
||||
void i915_audio_component_init(struct drm_i915_private *dev_priv)
|
||||
{
|
||||
int ret;
|
||||
|
||||
ret = component_add(dev_priv->dev->dev, &i915_audio_component_bind_ops);
|
||||
if (ret < 0) {
|
||||
DRM_ERROR("failed to add audio component (%d)\n", ret);
|
||||
/* continue with reduced functionality */
|
||||
return;
|
||||
}
|
||||
|
||||
dev_priv->audio_component_registered = true;
|
||||
}
|
||||
|
||||
/**
|
||||
* i915_audio_component_cleanup - deregister the audio component
|
||||
* @dev_priv: i915 device instance
|
||||
*
|
||||
* Deregisters the audio component, breaking any existing binding to the
|
||||
* corresponding snd_hda_intel driver's master component.
|
||||
*/
|
||||
void i915_audio_component_cleanup(struct drm_i915_private *dev_priv)
|
||||
{
|
||||
if (!dev_priv->audio_component_registered)
|
||||
return;
|
||||
|
||||
component_del(dev_priv->dev->dev, &i915_audio_component_bind_ops);
|
||||
dev_priv->audio_component_registered = false;
|
||||
}
|
||||
|
@ -314,7 +314,6 @@ parse_lfp_backlight(struct drm_i915_private *dev_priv, struct bdb_header *bdb)
|
||||
{
|
||||
const struct bdb_lfp_backlight_data *backlight_data;
|
||||
const struct bdb_lfp_backlight_data_entry *entry;
|
||||
const struct bdb_lfp_backlight_control_data *bl_ctrl_data;
|
||||
|
||||
backlight_data = find_section(bdb, BDB_LVDS_BACKLIGHT);
|
||||
if (!backlight_data)
|
||||
@ -327,7 +326,6 @@ parse_lfp_backlight(struct drm_i915_private *dev_priv, struct bdb_header *bdb)
|
||||
}
|
||||
|
||||
entry = &backlight_data->data[panel_type];
|
||||
bl_ctrl_data = &backlight_data->blc_ctl[panel_type];
|
||||
|
||||
dev_priv->vbt.backlight.present = entry->type == BDB_BACKLIGHT_TYPE_PWM;
|
||||
if (!dev_priv->vbt.backlight.present) {
|
||||
@ -339,30 +337,12 @@ parse_lfp_backlight(struct drm_i915_private *dev_priv, struct bdb_header *bdb)
|
||||
dev_priv->vbt.backlight.pwm_freq_hz = entry->pwm_freq_hz;
|
||||
dev_priv->vbt.backlight.active_low_pwm = entry->active_low_pwm;
|
||||
dev_priv->vbt.backlight.min_brightness = entry->min_brightness;
|
||||
|
||||
dev_priv->vbt.backlight.controller = 0;
|
||||
if (bdb->version >= 191) {
|
||||
dev_priv->vbt.backlight.present =
|
||||
bl_ctrl_data->pin == BLC_CONTROL_PIN_DDI;
|
||||
if (!dev_priv->vbt.backlight.present) {
|
||||
DRM_DEBUG_KMS("BL control pin is not DDI (pin %u)\n",
|
||||
bl_ctrl_data->pin);
|
||||
return;
|
||||
}
|
||||
if (bl_ctrl_data->controller == 1)
|
||||
dev_priv->vbt.backlight.controller =
|
||||
bl_ctrl_data->controller;
|
||||
}
|
||||
|
||||
DRM_DEBUG_KMS("VBT backlight PWM modulation frequency %u Hz, "
|
||||
"active %s, min brightness %u, level %u\n",
|
||||
dev_priv->vbt.backlight.pwm_freq_hz,
|
||||
dev_priv->vbt.backlight.active_low_pwm ? "low" : "high",
|
||||
dev_priv->vbt.backlight.min_brightness,
|
||||
backlight_data->level[panel_type]);
|
||||
|
||||
DRM_DEBUG_KMS("VBT BL controller %u\n",
|
||||
dev_priv->vbt.backlight.controller);
|
||||
}
|
||||
|
||||
/* Try to find sdvo panel data */
|
||||
|
@ -402,21 +402,10 @@ struct bdb_lfp_backlight_data_entry {
|
||||
u8 obsolete3;
|
||||
} __packed;
|
||||
|
||||
#define BLC_CONTROL_PIN_PMIC 0
|
||||
#define BLC_CONTROL_PIN_LPSS_PWM 1
|
||||
#define BLC_CONTROL_PIN_DDI 2
|
||||
#define BLC_CONTROL_PIN_CABC 3
|
||||
|
||||
struct bdb_lfp_backlight_control_data {
|
||||
u8 controller:4;
|
||||
u8 pin:4;
|
||||
} __packed;
|
||||
|
||||
struct bdb_lfp_backlight_data {
|
||||
u8 entry_size;
|
||||
struct bdb_lfp_backlight_data_entry data[16];
|
||||
u8 level[16];
|
||||
struct bdb_lfp_backlight_control_data blc_ctl[16];
|
||||
} __packed;
|
||||
|
||||
struct aimdb_header {
|
||||
|
@ -98,6 +98,8 @@ static void vlv_prepare_pll(struct intel_crtc *crtc,
|
||||
const struct intel_crtc_config *pipe_config);
|
||||
static void chv_prepare_pll(struct intel_crtc *crtc,
|
||||
const struct intel_crtc_config *pipe_config);
|
||||
static void intel_begin_crtc_commit(struct drm_crtc *crtc);
|
||||
static void intel_finish_crtc_commit(struct drm_crtc *crtc);
|
||||
|
||||
static struct intel_encoder *intel_find_encoder(struct intel_connector *connector, int pipe)
|
||||
{
|
||||
@ -2165,7 +2167,8 @@ static void intel_disable_primary_hw_plane(struct drm_plane *plane,
|
||||
struct drm_i915_private *dev_priv = dev->dev_private;
|
||||
struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
|
||||
|
||||
assert_pipe_enabled(dev_priv, intel_crtc->pipe);
|
||||
if (WARN_ON(!intel_crtc->active))
|
||||
return;
|
||||
|
||||
if (!intel_crtc->primary_enabled)
|
||||
return;
|
||||
@ -4036,7 +4039,7 @@ static void ironlake_pfit_enable(struct intel_crtc *crtc)
|
||||
}
|
||||
}
|
||||
|
||||
static void intel_enable_planes(struct drm_crtc *crtc)
|
||||
static void intel_enable_sprite_planes(struct drm_crtc *crtc)
|
||||
{
|
||||
struct drm_device *dev = crtc->dev;
|
||||
enum pipe pipe = to_intel_crtc(crtc)->pipe;
|
||||
@ -4050,7 +4053,7 @@ static void intel_enable_planes(struct drm_crtc *crtc)
|
||||
}
|
||||
}
|
||||
|
||||
static void intel_disable_planes(struct drm_crtc *crtc)
|
||||
static void intel_disable_sprite_planes(struct drm_crtc *crtc)
|
||||
{
|
||||
struct drm_device *dev = crtc->dev;
|
||||
enum pipe pipe = to_intel_crtc(crtc)->pipe;
|
||||
@ -4194,7 +4197,7 @@ static void intel_crtc_enable_planes(struct drm_crtc *crtc)
|
||||
int pipe = intel_crtc->pipe;
|
||||
|
||||
intel_enable_primary_hw_plane(crtc->primary, crtc);
|
||||
intel_enable_planes(crtc);
|
||||
intel_enable_sprite_planes(crtc);
|
||||
intel_crtc_update_cursor(crtc, true);
|
||||
intel_crtc_dpms_overlay(intel_crtc, true);
|
||||
|
||||
@ -4229,7 +4232,7 @@ static void intel_crtc_disable_planes(struct drm_crtc *crtc)
|
||||
|
||||
intel_crtc_dpms_overlay(intel_crtc, false);
|
||||
intel_crtc_update_cursor(crtc, false);
|
||||
intel_disable_planes(crtc);
|
||||
intel_disable_sprite_planes(crtc);
|
||||
intel_disable_primary_hw_plane(crtc->primary, crtc);
|
||||
|
||||
/*
|
||||
@ -4301,15 +4304,15 @@ static void ironlake_crtc_enable(struct drm_crtc *crtc)
|
||||
if (intel_crtc->config.has_pch_encoder)
|
||||
ironlake_pch_enable(crtc);
|
||||
|
||||
assert_vblank_disabled(crtc);
|
||||
drm_crtc_vblank_on(crtc);
|
||||
|
||||
for_each_encoder_on_crtc(dev, crtc, encoder)
|
||||
encoder->enable(encoder);
|
||||
|
||||
if (HAS_PCH_CPT(dev))
|
||||
cpt_verify_modeset(dev, intel_crtc->pipe);
|
||||
|
||||
assert_vblank_disabled(crtc);
|
||||
drm_crtc_vblank_on(crtc);
|
||||
|
||||
intel_crtc_enable_planes(crtc);
|
||||
}
|
||||
|
||||
@ -4421,14 +4424,14 @@ static void haswell_crtc_enable(struct drm_crtc *crtc)
|
||||
if (intel_crtc->config.dp_encoder_is_mst)
|
||||
intel_ddi_set_vc_payload_alloc(crtc, true);
|
||||
|
||||
assert_vblank_disabled(crtc);
|
||||
drm_crtc_vblank_on(crtc);
|
||||
|
||||
for_each_encoder_on_crtc(dev, crtc, encoder) {
|
||||
encoder->enable(encoder);
|
||||
intel_opregion_notify_encoder(encoder, true);
|
||||
}
|
||||
|
||||
assert_vblank_disabled(crtc);
|
||||
drm_crtc_vblank_on(crtc);
|
||||
|
||||
/* If we change the relative order between pipe/planes enabling, we need
|
||||
* to change the workaround. */
|
||||
haswell_mode_set_planes_workaround(intel_crtc);
|
||||
@ -4479,12 +4482,12 @@ static void ironlake_crtc_disable(struct drm_crtc *crtc)
|
||||
|
||||
intel_crtc_disable_planes(crtc);
|
||||
|
||||
drm_crtc_vblank_off(crtc);
|
||||
assert_vblank_disabled(crtc);
|
||||
|
||||
for_each_encoder_on_crtc(dev, crtc, encoder)
|
||||
encoder->disable(encoder);
|
||||
|
||||
drm_crtc_vblank_off(crtc);
|
||||
assert_vblank_disabled(crtc);
|
||||
|
||||
if (intel_crtc->config.has_pch_encoder)
|
||||
intel_set_pch_fifo_underrun_reporting(dev_priv, pipe, false);
|
||||
|
||||
@ -4543,14 +4546,14 @@ static void haswell_crtc_disable(struct drm_crtc *crtc)
|
||||
|
||||
intel_crtc_disable_planes(crtc);
|
||||
|
||||
drm_crtc_vblank_off(crtc);
|
||||
assert_vblank_disabled(crtc);
|
||||
|
||||
for_each_encoder_on_crtc(dev, crtc, encoder) {
|
||||
intel_opregion_notify_encoder(encoder, false);
|
||||
encoder->disable(encoder);
|
||||
}
|
||||
|
||||
drm_crtc_vblank_off(crtc);
|
||||
assert_vblank_disabled(crtc);
|
||||
|
||||
if (intel_crtc->config.has_pch_encoder)
|
||||
intel_set_pch_fifo_underrun_reporting(dev_priv, TRANSCODER_A,
|
||||
false);
|
||||
@ -5018,12 +5021,12 @@ static void valleyview_crtc_enable(struct drm_crtc *crtc)
|
||||
intel_update_watermarks(crtc);
|
||||
intel_enable_pipe(intel_crtc);
|
||||
|
||||
for_each_encoder_on_crtc(dev, crtc, encoder)
|
||||
encoder->enable(encoder);
|
||||
|
||||
assert_vblank_disabled(crtc);
|
||||
drm_crtc_vblank_on(crtc);
|
||||
|
||||
for_each_encoder_on_crtc(dev, crtc, encoder)
|
||||
encoder->enable(encoder);
|
||||
|
||||
intel_crtc_enable_planes(crtc);
|
||||
|
||||
/* Underruns don't raise interrupts, so check manually. */
|
||||
@ -5079,12 +5082,12 @@ static void i9xx_crtc_enable(struct drm_crtc *crtc)
|
||||
intel_update_watermarks(crtc);
|
||||
intel_enable_pipe(intel_crtc);
|
||||
|
||||
for_each_encoder_on_crtc(dev, crtc, encoder)
|
||||
encoder->enable(encoder);
|
||||
|
||||
assert_vblank_disabled(crtc);
|
||||
drm_crtc_vblank_on(crtc);
|
||||
|
||||
for_each_encoder_on_crtc(dev, crtc, encoder)
|
||||
encoder->enable(encoder);
|
||||
|
||||
intel_crtc_enable_planes(crtc);
|
||||
|
||||
/*
|
||||
@ -5156,12 +5159,12 @@ static void i9xx_crtc_disable(struct drm_crtc *crtc)
|
||||
*/
|
||||
intel_wait_for_vblank(dev, pipe);
|
||||
|
||||
drm_crtc_vblank_off(crtc);
|
||||
assert_vblank_disabled(crtc);
|
||||
|
||||
for_each_encoder_on_crtc(dev, crtc, encoder)
|
||||
encoder->disable(encoder);
|
||||
|
||||
drm_crtc_vblank_off(crtc);
|
||||
assert_vblank_disabled(crtc);
|
||||
|
||||
intel_disable_pipe(intel_crtc);
|
||||
|
||||
i9xx_pfit_disable(intel_crtc);
|
||||
@ -9613,7 +9616,6 @@ static int intel_crtc_page_flip(struct drm_crtc *crtc,
|
||||
struct drm_i915_gem_object *obj = intel_fb_obj(fb);
|
||||
struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
|
||||
struct drm_plane *primary = crtc->primary;
|
||||
struct intel_plane *intel_plane = to_intel_plane(primary);
|
||||
enum pipe pipe = intel_crtc->pipe;
|
||||
struct intel_unpin_work *work;
|
||||
struct intel_engine_cs *ring;
|
||||
@ -9772,15 +9774,7 @@ free_work:
|
||||
|
||||
if (ret == -EIO) {
|
||||
out_hang:
|
||||
ret = primary->funcs->update_plane(primary, crtc, fb,
|
||||
intel_plane->crtc_x,
|
||||
intel_plane->crtc_y,
|
||||
intel_plane->crtc_h,
|
||||
intel_plane->crtc_w,
|
||||
intel_plane->src_x,
|
||||
intel_plane->src_y,
|
||||
intel_plane->src_h,
|
||||
intel_plane->src_w);
|
||||
ret = intel_plane_restore(primary);
|
||||
if (ret == 0 && event) {
|
||||
spin_lock_irq(&dev->event_lock);
|
||||
drm_send_vblank_event(dev, pipe, event);
|
||||
@ -9793,6 +9787,8 @@ out_hang:
|
||||
static struct drm_crtc_helper_funcs intel_helper_funcs = {
|
||||
.mode_set_base_atomic = intel_pipe_set_base_atomic,
|
||||
.load_lut = intel_crtc_load_lut,
|
||||
.atomic_begin = intel_begin_crtc_commit,
|
||||
.atomic_flush = intel_finish_crtc_commit,
|
||||
};
|
||||
|
||||
/**
|
||||
@ -11673,7 +11669,7 @@ intel_prepare_plane_fb(struct drm_plane *plane,
|
||||
unsigned frontbuffer_bits = 0;
|
||||
int ret = 0;
|
||||
|
||||
if (WARN_ON(fb == plane->fb || !obj))
|
||||
if (!obj)
|
||||
return 0;
|
||||
|
||||
switch (plane->type) {
|
||||
@ -11737,13 +11733,20 @@ static int
|
||||
intel_check_primary_plane(struct drm_plane *plane,
|
||||
struct intel_plane_state *state)
|
||||
{
|
||||
struct drm_device *dev = plane->dev;
|
||||
struct drm_i915_private *dev_priv = dev->dev_private;
|
||||
struct drm_crtc *crtc = state->base.crtc;
|
||||
struct intel_crtc *intel_crtc;
|
||||
struct intel_plane *intel_plane = to_intel_plane(plane);
|
||||
struct drm_framebuffer *fb = state->base.fb;
|
||||
struct drm_rect *dest = &state->dst;
|
||||
struct drm_rect *src = &state->src;
|
||||
const struct drm_rect *clip = &state->clip;
|
||||
int ret;
|
||||
|
||||
crtc = crtc ? crtc : plane->crtc;
|
||||
intel_crtc = to_intel_crtc(crtc);
|
||||
|
||||
ret = drm_plane_helper_check_update(plane, crtc, fb,
|
||||
src, dest, clip,
|
||||
DRM_PLANE_HELPER_NO_SCALING,
|
||||
@ -11752,55 +11755,9 @@ intel_check_primary_plane(struct drm_plane *plane,
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
intel_crtc_wait_for_pending_flips(crtc);
|
||||
if (intel_crtc_has_pending_flip(crtc)) {
|
||||
DRM_ERROR("pipe is still busy with an old pageflip\n");
|
||||
return -EBUSY;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void
|
||||
intel_commit_primary_plane(struct drm_plane *plane,
|
||||
struct intel_plane_state *state)
|
||||
{
|
||||
struct drm_crtc *crtc = state->base.crtc;
|
||||
struct drm_framebuffer *fb = state->base.fb;
|
||||
struct drm_device *dev = plane->dev;
|
||||
struct drm_i915_private *dev_priv = dev->dev_private;
|
||||
struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
|
||||
struct drm_i915_gem_object *obj = intel_fb_obj(fb);
|
||||
struct intel_plane *intel_plane = to_intel_plane(plane);
|
||||
struct drm_rect *src = &state->src;
|
||||
enum pipe pipe = intel_plane->pipe;
|
||||
|
||||
if (!fb) {
|
||||
/*
|
||||
* 'prepare' is never called when plane is being disabled, so
|
||||
* we need to handle frontbuffer tracking here
|
||||
*/
|
||||
mutex_lock(&dev->struct_mutex);
|
||||
i915_gem_track_fb(intel_fb_obj(plane->fb), NULL,
|
||||
INTEL_FRONTBUFFER_PRIMARY(pipe));
|
||||
mutex_unlock(&dev->struct_mutex);
|
||||
}
|
||||
|
||||
plane->fb = fb;
|
||||
crtc->x = src->x1 >> 16;
|
||||
crtc->y = src->y1 >> 16;
|
||||
|
||||
intel_plane->crtc_x = state->orig_dst.x1;
|
||||
intel_plane->crtc_y = state->orig_dst.y1;
|
||||
intel_plane->crtc_w = drm_rect_width(&state->orig_dst);
|
||||
intel_plane->crtc_h = drm_rect_height(&state->orig_dst);
|
||||
intel_plane->src_x = state->orig_src.x1;
|
||||
intel_plane->src_y = state->orig_src.y1;
|
||||
intel_plane->src_w = drm_rect_width(&state->orig_src);
|
||||
intel_plane->src_h = drm_rect_height(&state->orig_src);
|
||||
intel_plane->obj = obj;
|
||||
|
||||
if (intel_crtc->active) {
|
||||
intel_crtc->atomic.wait_for_flips = true;
|
||||
|
||||
/*
|
||||
* FBC does not work on some platforms for rotated
|
||||
* planes, so disable it when rotation is not 0 and
|
||||
@ -11815,12 +11772,52 @@ intel_commit_primary_plane(struct drm_plane *plane,
|
||||
INTEL_INFO(dev)->gen <= 4 && !IS_G4X(dev) &&
|
||||
dev_priv->fbc.plane == intel_crtc->plane &&
|
||||
intel_plane->rotation != BIT(DRM_ROTATE_0)) {
|
||||
intel_fbc_disable(dev);
|
||||
intel_crtc->atomic.disable_fbc = true;
|
||||
}
|
||||
|
||||
if (state->visible) {
|
||||
bool was_enabled = intel_crtc->primary_enabled;
|
||||
/*
|
||||
* BDW signals flip done immediately if the plane
|
||||
* is disabled, even if the plane enable is already
|
||||
* armed to occur at the next vblank :(
|
||||
*/
|
||||
if (IS_BROADWELL(dev) && !intel_crtc->primary_enabled)
|
||||
intel_crtc->atomic.wait_vblank = true;
|
||||
}
|
||||
|
||||
intel_crtc->atomic.fb_bits |=
|
||||
INTEL_FRONTBUFFER_PRIMARY(intel_crtc->pipe);
|
||||
|
||||
intel_crtc->atomic.update_fbc = true;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void
|
||||
intel_commit_primary_plane(struct drm_plane *plane,
|
||||
struct intel_plane_state *state)
|
||||
{
|
||||
struct drm_crtc *crtc = state->base.crtc;
|
||||
struct drm_framebuffer *fb = state->base.fb;
|
||||
struct drm_device *dev = plane->dev;
|
||||
struct drm_i915_private *dev_priv = dev->dev_private;
|
||||
struct intel_crtc *intel_crtc;
|
||||
struct drm_i915_gem_object *obj = intel_fb_obj(fb);
|
||||
struct intel_plane *intel_plane = to_intel_plane(plane);
|
||||
struct drm_rect *src = &state->src;
|
||||
|
||||
crtc = crtc ? crtc : plane->crtc;
|
||||
intel_crtc = to_intel_crtc(crtc);
|
||||
|
||||
plane->fb = fb;
|
||||
crtc->x = src->x1 >> 16;
|
||||
crtc->y = src->y1 >> 16;
|
||||
|
||||
intel_plane->obj = obj;
|
||||
|
||||
if (intel_crtc->active) {
|
||||
if (state->visible) {
|
||||
/* FIXME: kill this fastboot hack */
|
||||
intel_update_pipe_size(intel_crtc);
|
||||
|
||||
@ -11828,14 +11825,6 @@ intel_commit_primary_plane(struct drm_plane *plane,
|
||||
|
||||
dev_priv->display.update_primary_plane(crtc, plane->fb,
|
||||
crtc->x, crtc->y);
|
||||
|
||||
/*
|
||||
* BDW signals flip done immediately if the plane
|
||||
* is disabled, even if the plane enable is already
|
||||
* armed to occur at the next vblank :(
|
||||
*/
|
||||
if (IS_BROADWELL(dev) && !was_enabled)
|
||||
intel_wait_for_vblank(dev, intel_crtc->pipe);
|
||||
} else {
|
||||
/*
|
||||
* If clipping results in a non-visible primary plane,
|
||||
@ -11846,110 +11835,121 @@ intel_commit_primary_plane(struct drm_plane *plane,
|
||||
*/
|
||||
intel_disable_primary_hw_plane(plane, crtc);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
intel_frontbuffer_flip(dev, INTEL_FRONTBUFFER_PRIMARY(pipe));
|
||||
static void intel_begin_crtc_commit(struct drm_crtc *crtc)
|
||||
{
|
||||
struct drm_device *dev = crtc->dev;
|
||||
struct drm_i915_private *dev_priv = dev->dev_private;
|
||||
struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
|
||||
struct intel_plane *intel_plane;
|
||||
struct drm_plane *p;
|
||||
unsigned fb_bits = 0;
|
||||
|
||||
/* Track fb's for any planes being disabled */
|
||||
list_for_each_entry(p, &dev->mode_config.plane_list, head) {
|
||||
intel_plane = to_intel_plane(p);
|
||||
|
||||
if (intel_crtc->atomic.disabled_planes &
|
||||
(1 << drm_plane_index(p))) {
|
||||
switch (p->type) {
|
||||
case DRM_PLANE_TYPE_PRIMARY:
|
||||
fb_bits = INTEL_FRONTBUFFER_PRIMARY(intel_plane->pipe);
|
||||
break;
|
||||
case DRM_PLANE_TYPE_CURSOR:
|
||||
fb_bits = INTEL_FRONTBUFFER_CURSOR(intel_plane->pipe);
|
||||
break;
|
||||
case DRM_PLANE_TYPE_OVERLAY:
|
||||
fb_bits = INTEL_FRONTBUFFER_SPRITE(intel_plane->pipe);
|
||||
break;
|
||||
}
|
||||
|
||||
mutex_lock(&dev->struct_mutex);
|
||||
i915_gem_track_fb(intel_fb_obj(p->fb), NULL, fb_bits);
|
||||
mutex_unlock(&dev->struct_mutex);
|
||||
}
|
||||
}
|
||||
|
||||
if (intel_crtc->atomic.wait_for_flips)
|
||||
intel_crtc_wait_for_pending_flips(crtc);
|
||||
|
||||
if (intel_crtc->atomic.disable_fbc)
|
||||
intel_fbc_disable(dev);
|
||||
|
||||
if (intel_crtc->atomic.pre_disable_primary)
|
||||
intel_pre_disable_primary(crtc);
|
||||
|
||||
if (intel_crtc->atomic.update_wm)
|
||||
intel_update_watermarks(crtc);
|
||||
|
||||
intel_runtime_pm_get(dev_priv);
|
||||
|
||||
/* Perform vblank evasion around commit operation */
|
||||
if (intel_crtc->active)
|
||||
intel_crtc->atomic.evade =
|
||||
intel_pipe_update_start(intel_crtc,
|
||||
&intel_crtc->atomic.start_vbl_count);
|
||||
}
|
||||
|
||||
static void intel_finish_crtc_commit(struct drm_crtc *crtc)
|
||||
{
|
||||
struct drm_device *dev = crtc->dev;
|
||||
struct drm_i915_private *dev_priv = dev->dev_private;
|
||||
struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
|
||||
struct drm_plane *p;
|
||||
|
||||
if (intel_crtc->atomic.evade)
|
||||
intel_pipe_update_end(intel_crtc,
|
||||
intel_crtc->atomic.start_vbl_count);
|
||||
|
||||
intel_runtime_pm_put(dev_priv);
|
||||
|
||||
if (intel_crtc->atomic.wait_vblank)
|
||||
intel_wait_for_vblank(dev, intel_crtc->pipe);
|
||||
|
||||
intel_frontbuffer_flip(dev, intel_crtc->atomic.fb_bits);
|
||||
|
||||
if (intel_crtc->atomic.update_fbc) {
|
||||
mutex_lock(&dev->struct_mutex);
|
||||
intel_fbc_update(dev);
|
||||
mutex_unlock(&dev->struct_mutex);
|
||||
}
|
||||
}
|
||||
|
||||
int
|
||||
intel_update_plane(struct drm_plane *plane, struct drm_crtc *crtc,
|
||||
struct drm_framebuffer *fb, int crtc_x, int crtc_y,
|
||||
unsigned int crtc_w, unsigned int crtc_h,
|
||||
uint32_t src_x, uint32_t src_y,
|
||||
uint32_t src_w, uint32_t src_h)
|
||||
{
|
||||
struct drm_device *dev = plane->dev;
|
||||
struct drm_i915_private *dev_priv = dev->dev_private;
|
||||
struct drm_framebuffer *old_fb = plane->fb;
|
||||
struct intel_plane_state state;
|
||||
struct intel_plane *intel_plane = to_intel_plane(plane);
|
||||
struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
|
||||
int ret;
|
||||
if (intel_crtc->atomic.post_enable_primary)
|
||||
intel_post_enable_primary(crtc);
|
||||
|
||||
state.base.crtc = crtc ? crtc : plane->crtc;
|
||||
state.base.fb = fb;
|
||||
drm_for_each_legacy_plane(p, &dev->mode_config.plane_list)
|
||||
if (intel_crtc->atomic.update_sprite_watermarks & drm_plane_index(p))
|
||||
intel_update_sprite_watermarks(p, crtc, 0, 0, 0,
|
||||
false, false);
|
||||
|
||||
/* sample coordinates in 16.16 fixed point */
|
||||
state.src.x1 = src_x;
|
||||
state.src.x2 = src_x + src_w;
|
||||
state.src.y1 = src_y;
|
||||
state.src.y2 = src_y + src_h;
|
||||
|
||||
/* integer pixels */
|
||||
state.dst.x1 = crtc_x;
|
||||
state.dst.x2 = crtc_x + crtc_w;
|
||||
state.dst.y1 = crtc_y;
|
||||
state.dst.y2 = crtc_y + crtc_h;
|
||||
|
||||
state.clip.x1 = 0;
|
||||
state.clip.y1 = 0;
|
||||
state.clip.x2 = intel_crtc->active ? intel_crtc->config.pipe_src_w : 0;
|
||||
state.clip.y2 = intel_crtc->active ? intel_crtc->config.pipe_src_h : 0;
|
||||
|
||||
state.orig_src = state.src;
|
||||
state.orig_dst = state.dst;
|
||||
|
||||
ret = intel_plane->check_plane(plane, &state);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
if (fb != old_fb && fb) {
|
||||
ret = intel_prepare_plane_fb(plane, fb);
|
||||
if (ret)
|
||||
return ret;
|
||||
}
|
||||
|
||||
intel_runtime_pm_get(dev_priv);
|
||||
intel_plane->commit_plane(plane, &state);
|
||||
intel_runtime_pm_put(dev_priv);
|
||||
|
||||
if (fb != old_fb && old_fb) {
|
||||
if (intel_crtc->active)
|
||||
intel_wait_for_vblank(dev, intel_crtc->pipe);
|
||||
intel_cleanup_plane_fb(plane, old_fb);
|
||||
}
|
||||
|
||||
plane->fb = fb;
|
||||
|
||||
return 0;
|
||||
memset(&intel_crtc->atomic, 0, sizeof(intel_crtc->atomic));
|
||||
}
|
||||
|
||||
/**
|
||||
* intel_disable_plane - disable a plane
|
||||
* @plane: plane to disable
|
||||
* intel_plane_destroy - destroy a plane
|
||||
* @plane: plane to destroy
|
||||
*
|
||||
* General disable handler for all plane types.
|
||||
* Common destruction function for all types of planes (primary, cursor,
|
||||
* sprite).
|
||||
*/
|
||||
int
|
||||
intel_disable_plane(struct drm_plane *plane)
|
||||
{
|
||||
if (!plane->fb)
|
||||
return 0;
|
||||
|
||||
if (WARN_ON(!plane->crtc))
|
||||
return -EINVAL;
|
||||
|
||||
return plane->funcs->update_plane(plane, plane->crtc, NULL,
|
||||
0, 0, 0, 0, 0, 0, 0, 0);
|
||||
}
|
||||
|
||||
/* Common destruction function for both primary and cursor planes */
|
||||
static void intel_plane_destroy(struct drm_plane *plane)
|
||||
void intel_plane_destroy(struct drm_plane *plane)
|
||||
{
|
||||
struct intel_plane *intel_plane = to_intel_plane(plane);
|
||||
intel_plane_destroy_state(plane, plane->state);
|
||||
drm_plane_cleanup(plane);
|
||||
kfree(intel_plane);
|
||||
}
|
||||
|
||||
static const struct drm_plane_funcs intel_primary_plane_funcs = {
|
||||
.update_plane = intel_update_plane,
|
||||
.disable_plane = intel_disable_plane,
|
||||
.update_plane = drm_plane_helper_update,
|
||||
.disable_plane = drm_plane_helper_disable,
|
||||
.destroy = intel_plane_destroy,
|
||||
.set_property = intel_plane_set_property
|
||||
.set_property = intel_plane_set_property,
|
||||
.atomic_duplicate_state = intel_plane_duplicate_state,
|
||||
.atomic_destroy_state = intel_plane_destroy_state,
|
||||
|
||||
};
|
||||
|
||||
static struct drm_plane *intel_primary_plane_create(struct drm_device *dev,
|
||||
@ -11963,6 +11963,12 @@ static struct drm_plane *intel_primary_plane_create(struct drm_device *dev,
|
||||
if (primary == NULL)
|
||||
return NULL;
|
||||
|
||||
primary->base.state = intel_plane_duplicate_state(&primary->base);
|
||||
if (primary->base.state == NULL) {
|
||||
kfree(primary);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
primary->can_scale = false;
|
||||
primary->max_downscale = 1;
|
||||
primary->pipe = pipe;
|
||||
@ -11998,6 +12004,8 @@ static struct drm_plane *intel_primary_plane_create(struct drm_device *dev,
|
||||
primary->rotation);
|
||||
}
|
||||
|
||||
drm_plane_helper_add(&primary->base, &intel_plane_helper_funcs);
|
||||
|
||||
return &primary->base;
|
||||
}
|
||||
|
||||
@ -12006,16 +12014,19 @@ intel_check_cursor_plane(struct drm_plane *plane,
|
||||
struct intel_plane_state *state)
|
||||
{
|
||||
struct drm_crtc *crtc = state->base.crtc;
|
||||
struct drm_device *dev = crtc->dev;
|
||||
struct drm_device *dev = plane->dev;
|
||||
struct drm_framebuffer *fb = state->base.fb;
|
||||
struct drm_rect *dest = &state->dst;
|
||||
struct drm_rect *src = &state->src;
|
||||
const struct drm_rect *clip = &state->clip;
|
||||
struct drm_i915_gem_object *obj = intel_fb_obj(fb);
|
||||
int crtc_w, crtc_h;
|
||||
struct intel_crtc *intel_crtc;
|
||||
unsigned stride;
|
||||
int ret;
|
||||
|
||||
crtc = crtc ? crtc : plane->crtc;
|
||||
intel_crtc = to_intel_crtc(crtc);
|
||||
|
||||
ret = drm_plane_helper_check_update(plane, crtc, fb,
|
||||
src, dest, clip,
|
||||
DRM_PLANE_HELPER_NO_SCALING,
|
||||
@ -12027,18 +12038,17 @@ intel_check_cursor_plane(struct drm_plane *plane,
|
||||
|
||||
/* if we want to turn off the cursor ignore width and height */
|
||||
if (!obj)
|
||||
return 0;
|
||||
goto finish;
|
||||
|
||||
/* Check for which cursor types we support */
|
||||
crtc_w = drm_rect_width(&state->orig_dst);
|
||||
crtc_h = drm_rect_height(&state->orig_dst);
|
||||
if (!cursor_size_ok(dev, crtc_w, crtc_h)) {
|
||||
DRM_DEBUG("Cursor dimension not supported\n");
|
||||
if (!cursor_size_ok(dev, state->base.crtc_w, state->base.crtc_h)) {
|
||||
DRM_DEBUG("Cursor dimension %dx%d not supported\n",
|
||||
state->base.crtc_w, state->base.crtc_h);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
stride = roundup_pow_of_two(crtc_w) * 4;
|
||||
if (obj->base.size < stride * crtc_h) {
|
||||
stride = roundup_pow_of_two(state->base.crtc_w) * 4;
|
||||
if (obj->base.size < stride * state->base.crtc_h) {
|
||||
DRM_DEBUG_KMS("buffer is too small\n");
|
||||
return -ENOMEM;
|
||||
}
|
||||
@ -12054,6 +12064,15 @@ intel_check_cursor_plane(struct drm_plane *plane,
|
||||
}
|
||||
mutex_unlock(&dev->struct_mutex);
|
||||
|
||||
finish:
|
||||
if (intel_crtc->active) {
|
||||
if (intel_crtc->cursor_width != state->base.crtc_w)
|
||||
intel_crtc->atomic.update_wm = true;
|
||||
|
||||
intel_crtc->atomic.fb_bits |=
|
||||
INTEL_FRONTBUFFER_CURSOR(intel_crtc->pipe);
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
@ -12062,43 +12081,24 @@ intel_commit_cursor_plane(struct drm_plane *plane,
|
||||
struct intel_plane_state *state)
|
||||
{
|
||||
struct drm_crtc *crtc = state->base.crtc;
|
||||
struct drm_device *dev = crtc->dev;
|
||||
struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
|
||||
struct drm_device *dev = plane->dev;
|
||||
struct intel_crtc *intel_crtc;
|
||||
struct intel_plane *intel_plane = to_intel_plane(plane);
|
||||
struct drm_i915_gem_object *obj = intel_fb_obj(state->base.fb);
|
||||
struct drm_i915_gem_object *old_obj = intel_fb_obj(plane->fb);
|
||||
enum pipe pipe = intel_crtc->pipe;
|
||||
unsigned old_width;
|
||||
uint32_t addr;
|
||||
|
||||
plane->fb = state->base.fb;
|
||||
crtc->cursor_x = state->orig_dst.x1;
|
||||
crtc->cursor_y = state->orig_dst.y1;
|
||||
crtc = crtc ? crtc : plane->crtc;
|
||||
intel_crtc = to_intel_crtc(crtc);
|
||||
|
||||
plane->fb = state->base.fb;
|
||||
crtc->cursor_x = state->base.crtc_x;
|
||||
crtc->cursor_y = state->base.crtc_y;
|
||||
|
||||
intel_plane->crtc_x = state->orig_dst.x1;
|
||||
intel_plane->crtc_y = state->orig_dst.y1;
|
||||
intel_plane->crtc_w = drm_rect_width(&state->orig_dst);
|
||||
intel_plane->crtc_h = drm_rect_height(&state->orig_dst);
|
||||
intel_plane->src_x = state->orig_src.x1;
|
||||
intel_plane->src_y = state->orig_src.y1;
|
||||
intel_plane->src_w = drm_rect_width(&state->orig_src);
|
||||
intel_plane->src_h = drm_rect_height(&state->orig_src);
|
||||
intel_plane->obj = obj;
|
||||
|
||||
if (intel_crtc->cursor_bo == obj)
|
||||
goto update;
|
||||
|
||||
/*
|
||||
* 'prepare' is only called when fb != NULL; we still need to update
|
||||
* frontbuffer tracking for the 'disable' case here.
|
||||
*/
|
||||
if (!obj) {
|
||||
mutex_lock(&dev->struct_mutex);
|
||||
i915_gem_track_fb(old_obj, NULL,
|
||||
INTEL_FRONTBUFFER_CURSOR(pipe));
|
||||
mutex_unlock(&dev->struct_mutex);
|
||||
}
|
||||
|
||||
if (!obj)
|
||||
addr = 0;
|
||||
else if (!INTEL_INFO(dev)->cursor_needs_physical)
|
||||
@ -12109,25 +12109,20 @@ intel_commit_cursor_plane(struct drm_plane *plane,
|
||||
intel_crtc->cursor_addr = addr;
|
||||
intel_crtc->cursor_bo = obj;
|
||||
update:
|
||||
old_width = intel_crtc->cursor_width;
|
||||
intel_crtc->cursor_width = state->base.crtc_w;
|
||||
intel_crtc->cursor_height = state->base.crtc_h;
|
||||
|
||||
intel_crtc->cursor_width = drm_rect_width(&state->orig_dst);
|
||||
intel_crtc->cursor_height = drm_rect_height(&state->orig_dst);
|
||||
|
||||
if (intel_crtc->active) {
|
||||
if (old_width != intel_crtc->cursor_width)
|
||||
intel_update_watermarks(crtc);
|
||||
if (intel_crtc->active)
|
||||
intel_crtc_update_cursor(crtc, state->visible);
|
||||
|
||||
intel_frontbuffer_flip(dev, INTEL_FRONTBUFFER_CURSOR(pipe));
|
||||
}
|
||||
}
|
||||
|
||||
static const struct drm_plane_funcs intel_cursor_plane_funcs = {
|
||||
.update_plane = intel_update_plane,
|
||||
.disable_plane = intel_disable_plane,
|
||||
.update_plane = drm_plane_helper_update,
|
||||
.disable_plane = drm_plane_helper_disable,
|
||||
.destroy = intel_plane_destroy,
|
||||
.set_property = intel_plane_set_property,
|
||||
.atomic_duplicate_state = intel_plane_duplicate_state,
|
||||
.atomic_destroy_state = intel_plane_destroy_state,
|
||||
};
|
||||
|
||||
static struct drm_plane *intel_cursor_plane_create(struct drm_device *dev,
|
||||
@ -12139,6 +12134,12 @@ static struct drm_plane *intel_cursor_plane_create(struct drm_device *dev,
|
||||
if (cursor == NULL)
|
||||
return NULL;
|
||||
|
||||
cursor->base.state = intel_plane_duplicate_state(&cursor->base);
|
||||
if (cursor->base.state == NULL) {
|
||||
kfree(cursor);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
cursor->can_scale = false;
|
||||
cursor->max_downscale = 1;
|
||||
cursor->pipe = pipe;
|
||||
@ -12165,6 +12166,8 @@ static struct drm_plane *intel_cursor_plane_create(struct drm_device *dev,
|
||||
cursor->rotation);
|
||||
}
|
||||
|
||||
drm_plane_helper_add(&cursor->base, &intel_plane_helper_funcs);
|
||||
|
||||
return &cursor->base;
|
||||
}
|
||||
|
||||
@ -12390,14 +12393,16 @@ static void intel_setup_outputs(struct drm_device *dev)
|
||||
* eDP ports. Consult the VBT as well as DP_DETECTED to
|
||||
* detect eDP ports.
|
||||
*/
|
||||
if (I915_READ(VLV_DISPLAY_BASE + GEN4_HDMIB) & SDVO_DETECTED)
|
||||
if (I915_READ(VLV_DISPLAY_BASE + GEN4_HDMIB) & SDVO_DETECTED &&
|
||||
!intel_dp_is_edp(dev, PORT_B))
|
||||
intel_hdmi_init(dev, VLV_DISPLAY_BASE + GEN4_HDMIB,
|
||||
PORT_B);
|
||||
if (I915_READ(VLV_DISPLAY_BASE + DP_B) & DP_DETECTED ||
|
||||
intel_dp_is_edp(dev, PORT_B))
|
||||
intel_dp_init(dev, VLV_DISPLAY_BASE + DP_B, PORT_B);
|
||||
|
||||
if (I915_READ(VLV_DISPLAY_BASE + GEN4_HDMIC) & SDVO_DETECTED)
|
||||
if (I915_READ(VLV_DISPLAY_BASE + GEN4_HDMIC) & SDVO_DETECTED &&
|
||||
!intel_dp_is_edp(dev, PORT_C))
|
||||
intel_hdmi_init(dev, VLV_DISPLAY_BASE + GEN4_HDMIC,
|
||||
PORT_C);
|
||||
if (I915_READ(VLV_DISPLAY_BASE + DP_C) & DP_DETECTED ||
|
||||
|
@ -3773,7 +3773,7 @@ go_again:
|
||||
intel_dp_stop_link_train(intel_dp);
|
||||
}
|
||||
|
||||
DRM_DEBUG_KMS("got esi %02x %02x %02x\n", esi[0], esi[1], esi[2]);
|
||||
DRM_DEBUG_KMS("got esi %3ph\n", esi);
|
||||
ret = drm_dp_mst_hpd_irq(&intel_dp->mst_mgr, esi, &handled);
|
||||
|
||||
if (handled) {
|
||||
@ -3789,7 +3789,7 @@ go_again:
|
||||
|
||||
bret = intel_dp_get_sink_irq_esi(intel_dp, esi);
|
||||
if (bret == true) {
|
||||
DRM_DEBUG_KMS("got esi2 %02x %02x %02x\n", esi[0], esi[1], esi[2]);
|
||||
DRM_DEBUG_KMS("got esi2 %3ph\n", esi);
|
||||
goto go_again;
|
||||
}
|
||||
} else
|
||||
|
@ -248,9 +248,13 @@ struct intel_plane_state {
|
||||
struct drm_rect src;
|
||||
struct drm_rect dst;
|
||||
struct drm_rect clip;
|
||||
struct drm_rect orig_src;
|
||||
struct drm_rect orig_dst;
|
||||
bool visible;
|
||||
|
||||
/*
|
||||
* used only for sprite planes to determine when to implicitly
|
||||
* enable/disable the primary plane
|
||||
*/
|
||||
bool hides_primary;
|
||||
};
|
||||
|
||||
struct intel_plane_config {
|
||||
@ -415,6 +419,32 @@ struct skl_pipe_wm {
|
||||
uint32_t linetime;
|
||||
};
|
||||
|
||||
/*
|
||||
* Tracking of operations that need to be performed at the beginning/end of an
|
||||
* atomic commit, outside the atomic section where interrupts are disabled.
|
||||
* These are generally operations that grab mutexes or might otherwise sleep
|
||||
* and thus can't be run with interrupts disabled.
|
||||
*/
|
||||
struct intel_crtc_atomic_commit {
|
||||
/* vblank evasion */
|
||||
bool evade;
|
||||
unsigned start_vbl_count;
|
||||
|
||||
/* Sleepable operations to perform before commit */
|
||||
bool wait_for_flips;
|
||||
bool disable_fbc;
|
||||
bool pre_disable_primary;
|
||||
bool update_wm;
|
||||
unsigned disabled_planes;
|
||||
|
||||
/* Sleepable operations to perform after commit */
|
||||
unsigned fb_bits;
|
||||
bool wait_vblank;
|
||||
bool update_fbc;
|
||||
bool post_enable_primary;
|
||||
unsigned update_sprite_watermarks;
|
||||
};
|
||||
|
||||
struct intel_crtc {
|
||||
struct drm_crtc base;
|
||||
enum pipe pipe;
|
||||
@ -468,6 +498,8 @@ struct intel_crtc {
|
||||
|
||||
int scanline_offset;
|
||||
struct intel_mmio_flip mmio_flip;
|
||||
|
||||
struct intel_crtc_atomic_commit atomic;
|
||||
};
|
||||
|
||||
struct intel_plane_wm_parameters {
|
||||
@ -485,10 +517,6 @@ struct intel_plane {
|
||||
struct drm_i915_gem_object *obj;
|
||||
bool can_scale;
|
||||
int max_downscale;
|
||||
int crtc_x, crtc_y;
|
||||
unsigned int crtc_w, crtc_h;
|
||||
uint32_t src_x, src_y;
|
||||
uint32_t src_w, src_h;
|
||||
unsigned int rotation;
|
||||
|
||||
/* Since we need to change the watermarks before/after
|
||||
@ -542,6 +570,7 @@ struct cxsr_latency {
|
||||
#define to_intel_encoder(x) container_of(x, struct intel_encoder, base)
|
||||
#define to_intel_framebuffer(x) container_of(x, struct intel_framebuffer, base)
|
||||
#define to_intel_plane(x) container_of(x, struct intel_plane, base)
|
||||
#define to_intel_plane_state(x) container_of(x, struct intel_plane_state, base)
|
||||
#define intel_fb_obj(x) (x ? to_intel_framebuffer(x)->obj : NULL)
|
||||
|
||||
struct intel_hdmi {
|
||||
@ -874,6 +903,8 @@ void intel_fb_obj_flush(struct drm_i915_gem_object *obj, bool retire);
|
||||
void intel_init_audio(struct drm_device *dev);
|
||||
void intel_audio_codec_enable(struct intel_encoder *encoder);
|
||||
void intel_audio_codec_disable(struct intel_encoder *encoder);
|
||||
void i915_audio_component_init(struct drm_i915_private *dev_priv);
|
||||
void i915_audio_component_cleanup(struct drm_i915_private *dev_priv);
|
||||
|
||||
/* intel_display.c */
|
||||
bool intel_has_pending_fb_unpin(struct drm_device *dev);
|
||||
@ -1021,6 +1052,7 @@ int intel_update_plane(struct drm_plane *plane, struct drm_crtc *crtc,
|
||||
uint32_t src_x, uint32_t src_y,
|
||||
uint32_t src_w, uint32_t src_h);
|
||||
int intel_disable_plane(struct drm_plane *plane);
|
||||
void intel_plane_destroy(struct drm_plane *plane);
|
||||
|
||||
/* intel_dp_mst.c */
|
||||
int intel_dp_mst_encoder_init(struct intel_digital_port *intel_dig_port, int conn_id);
|
||||
@ -1214,8 +1246,16 @@ int intel_sprite_get_colorkey(struct drm_device *dev, void *data,
|
||||
bool intel_pipe_update_start(struct intel_crtc *crtc,
|
||||
uint32_t *start_vbl_count);
|
||||
void intel_pipe_update_end(struct intel_crtc *crtc, u32 start_vbl_count);
|
||||
void intel_post_enable_primary(struct drm_crtc *crtc);
|
||||
void intel_pre_disable_primary(struct drm_crtc *crtc);
|
||||
|
||||
/* intel_tv.c */
|
||||
void intel_tv_init(struct drm_device *dev);
|
||||
|
||||
/* intel_atomic.c */
|
||||
struct drm_plane_state *intel_plane_duplicate_state(struct drm_plane *plane);
|
||||
void intel_plane_destroy_state(struct drm_plane *plane,
|
||||
struct drm_plane_state *state);
|
||||
extern const struct drm_plane_helper_funcs intel_plane_helper_funcs;
|
||||
|
||||
#endif /* __INTEL_DRV_H__ */
|
||||
|
@ -1137,6 +1137,7 @@ static int gen8_init_common_ring(struct intel_engine_cs *ring)
|
||||
_MASKED_BIT_DISABLE(GFX_REPLAY_MODE) |
|
||||
_MASKED_BIT_ENABLE(GFX_RUN_LIST_ENABLE));
|
||||
POSTING_READ(RING_MODE_GEN7(ring));
|
||||
ring->next_context_status_buffer = 0;
|
||||
DRM_DEBUG_DRIVER("Execlists enabled for %s\n", ring->name);
|
||||
|
||||
memset(&ring->hangcheck, 0, sizeof(ring->hangcheck));
|
||||
@ -1394,7 +1395,6 @@ static int logical_ring_init(struct drm_device *dev, struct intel_engine_cs *rin
|
||||
INIT_LIST_HEAD(&ring->execlist_queue);
|
||||
INIT_LIST_HEAD(&ring->execlist_retired_req_list);
|
||||
spin_lock_init(&ring->execlist_lock);
|
||||
ring->next_context_status_buffer = 0;
|
||||
|
||||
ret = i915_cmd_parser_init_ring(ring);
|
||||
if (ret)
|
||||
|
@ -4681,8 +4681,7 @@ static void cherryview_enable_rps(struct drm_device *dev)
|
||||
I915_WRITE(RING_MAX_IDLE(ring->mmio_base), 10);
|
||||
I915_WRITE(GEN6_RC_SLEEP, 0);
|
||||
|
||||
/* TO threshold set to 1750 us ( 0x557 * 1.28 us) */
|
||||
I915_WRITE(GEN6_RC6_THRESHOLD, 0x557);
|
||||
I915_WRITE(GEN6_RC6_THRESHOLD, 50000); /* 50/125ms per EI */
|
||||
|
||||
/* allows RC6 residency counter to work */
|
||||
I915_WRITE(VLV_COUNTER_CONTROL,
|
||||
@ -4696,7 +4695,7 @@ static void cherryview_enable_rps(struct drm_device *dev)
|
||||
/* 3: Enable RC6 */
|
||||
if ((intel_enable_rc6(dev) & INTEL_RC6_ENABLE) &&
|
||||
(pcbr >> VLV_PCBR_ADDR_SHIFT))
|
||||
rc6_mode = GEN7_RC_CTL_TO_MODE;
|
||||
rc6_mode = GEN6_RC_CTL_EI_MODE(1);
|
||||
|
||||
I915_WRITE(GEN6_RC_CONTROL, rc6_mode);
|
||||
|
||||
@ -5974,6 +5973,10 @@ static void haswell_init_clock_gating(struct drm_device *dev)
|
||||
I915_WRITE(GEN7_GT_MODE,
|
||||
_MASKED_FIELD(GEN6_WIZ_HASHING_MASK, GEN6_WIZ_HASHING_16x4));
|
||||
|
||||
/* WaSampleCChickenBitEnable:hsw */
|
||||
I915_WRITE(HALF_SLICE_CHICKEN3,
|
||||
_MASKED_BIT_ENABLE(HSW_SAMPLE_C_PERFORMANCE));
|
||||
|
||||
/* WaSwitchSolVfFArbitrationPriority:hsw */
|
||||
I915_WRITE(GAM_ECOCHK, I915_READ(GAM_ECOCHK) | HSW_ECOCHK_ARB_PRIO_SOL);
|
||||
|
||||
|
@ -143,7 +143,6 @@ static void hsw_psr_enable_sink(struct intel_dp *intel_dp)
|
||||
struct drm_i915_private *dev_priv = dev->dev_private;
|
||||
uint32_t aux_clock_divider;
|
||||
int precharge = 0x3;
|
||||
bool only_standby = dev_priv->vbt.psr.full_link;
|
||||
static const uint8_t aux_msg[] = {
|
||||
[0] = DP_AUX_NATIVE_WRITE << 4,
|
||||
[1] = DP_SET_POWER >> 8,
|
||||
@ -157,16 +156,13 @@ static void hsw_psr_enable_sink(struct intel_dp *intel_dp)
|
||||
|
||||
aux_clock_divider = intel_dp->get_aux_clock_divider(intel_dp, 0);
|
||||
|
||||
if (IS_BROADWELL(dev) && dig_port->port != PORT_A)
|
||||
only_standby = true;
|
||||
|
||||
/* Enable PSR in sink */
|
||||
if (intel_dp->psr_dpcd[1] & DP_PSR_NO_TRAIN_ON_EXIT || only_standby)
|
||||
drm_dp_dpcd_writeb(&intel_dp->aux, DP_PSR_EN_CFG,
|
||||
DP_PSR_ENABLE & ~DP_PSR_MAIN_LINK_ACTIVE);
|
||||
else
|
||||
if (dev_priv->psr.link_standby)
|
||||
drm_dp_dpcd_writeb(&intel_dp->aux, DP_PSR_EN_CFG,
|
||||
DP_PSR_ENABLE | DP_PSR_MAIN_LINK_ACTIVE);
|
||||
else
|
||||
drm_dp_dpcd_writeb(&intel_dp->aux, DP_PSR_EN_CFG,
|
||||
DP_PSR_ENABLE & ~DP_PSR_MAIN_LINK_ACTIVE);
|
||||
|
||||
/* Setup AUX registers */
|
||||
for (i = 0; i < sizeof(aux_msg); i += 4)
|
||||
@ -226,12 +222,8 @@ static void hsw_psr_enable_source(struct intel_dp *intel_dp)
|
||||
dev_priv->vbt.psr.idle_frames + 1 : 2;
|
||||
uint32_t val = 0x0;
|
||||
const uint32_t link_entry_time = EDP_PSR_MIN_LINK_ENTRY_TIME_8_LINES;
|
||||
bool only_standby = false;
|
||||
|
||||
if (IS_BROADWELL(dev) && dig_port->port != PORT_A)
|
||||
only_standby = true;
|
||||
|
||||
if (intel_dp->psr_dpcd[1] & DP_PSR_NO_TRAIN_ON_EXIT || only_standby) {
|
||||
if (dev_priv->psr.link_standby) {
|
||||
val |= EDP_PSR_LINK_STANDBY;
|
||||
val |= EDP_PSR_TP2_TP3_TIME_0us;
|
||||
val |= EDP_PSR_TP1_TIME_0us;
|
||||
@ -270,22 +262,19 @@ static bool intel_psr_match_conditions(struct intel_dp *intel_dp)
|
||||
return false;
|
||||
}
|
||||
|
||||
/* Below limitations aren't valid for Broadwell */
|
||||
if (IS_BROADWELL(dev))
|
||||
goto out;
|
||||
|
||||
if (I915_READ(HSW_STEREO_3D_CTL(intel_crtc->config.cpu_transcoder)) &
|
||||
S3D_ENABLE) {
|
||||
if (IS_HASWELL(dev) &&
|
||||
I915_READ(HSW_STEREO_3D_CTL(intel_crtc->config.cpu_transcoder)) &
|
||||
S3D_ENABLE) {
|
||||
DRM_DEBUG_KMS("PSR condition failed: Stereo 3D is Enabled\n");
|
||||
return false;
|
||||
}
|
||||
|
||||
if (intel_crtc->config.adjusted_mode.flags & DRM_MODE_FLAG_INTERLACE) {
|
||||
if (IS_HASWELL(dev) &&
|
||||
intel_crtc->config.adjusted_mode.flags & DRM_MODE_FLAG_INTERLACE) {
|
||||
DRM_DEBUG_KMS("PSR condition failed: Interlaced is Enabled\n");
|
||||
return false;
|
||||
}
|
||||
|
||||
out:
|
||||
dev_priv->psr.source_ok = true;
|
||||
return true;
|
||||
}
|
||||
@ -344,6 +333,13 @@ void intel_psr_enable(struct intel_dp *intel_dp)
|
||||
if (!intel_psr_match_conditions(intel_dp))
|
||||
goto unlock;
|
||||
|
||||
/* First we check VBT, but we must respect sink and source
|
||||
* known restrictions */
|
||||
dev_priv->psr.link_standby = dev_priv->vbt.psr.full_link;
|
||||
if ((intel_dp->psr_dpcd[1] & DP_PSR_NO_TRAIN_ON_EXIT) ||
|
||||
(IS_BROADWELL(dev) && intel_dig_port->port != PORT_A))
|
||||
dev_priv->psr.link_standby = true;
|
||||
|
||||
dev_priv->psr.busy_frontbuffer_bits = 0;
|
||||
|
||||
if (HAS_DDI(dev)) {
|
||||
@ -620,13 +616,11 @@ void intel_psr_flush(struct drm_device *dev,
|
||||
|
||||
/*
|
||||
* On Valleyview and Cherryview we don't use hardware tracking so
|
||||
* sprite plane updates or cursor moves don't result in a PSR
|
||||
* any plane updates or cursor moves don't result in a PSR
|
||||
* invalidating. Which means we need to manually fake this in
|
||||
* software for all flushes, not just when we've seen a preceding
|
||||
* invalidation through frontbuffer rendering. */
|
||||
if (!HAS_DDI(dev) &&
|
||||
((frontbuffer_bits & INTEL_FRONTBUFFER_SPRITE(pipe)) ||
|
||||
(frontbuffer_bits & INTEL_FRONTBUFFER_CURSOR(pipe))))
|
||||
if (!HAS_DDI(dev))
|
||||
intel_psr_exit(dev);
|
||||
|
||||
if (!dev_priv->psr.active && !dev_priv->psr.busy_frontbuffer_bits)
|
||||
|
@ -796,6 +796,16 @@ static int bdw_init_workarounds(struct intel_engine_cs *ring)
|
||||
HDC_DONOT_FETCH_MEM_WHEN_MASKED |
|
||||
(IS_BDW_GT3(dev) ? HDC_FENCE_DEST_SLM_DISABLE : 0));
|
||||
|
||||
/* From the Haswell PRM, Command Reference: Registers, CACHE_MODE_0:
|
||||
* "The Hierarchical Z RAW Stall Optimization allows non-overlapping
|
||||
* polygons in the same 8x4 pixel/sample area to be processed without
|
||||
* stalling waiting for the earlier ones to write to Hierarchical Z
|
||||
* buffer."
|
||||
*
|
||||
* This optimization is off by default for Broadwell; turn it on.
|
||||
*/
|
||||
WA_CLR_BIT_MASKED(CACHE_MODE_0_GEN7, HIZ_RAW_STALL_OPT_DISABLE);
|
||||
|
||||
/* Wa4x4STCOptimizationDisable:bdw */
|
||||
WA_SET_BIT_MASKED(CACHE_MODE_1,
|
||||
GEN8_4x4_STC_OPTIMIZATION_DISABLE);
|
||||
@ -836,6 +846,14 @@ static int chv_init_workarounds(struct intel_engine_cs *ring)
|
||||
HDC_FORCE_NON_COHERENT |
|
||||
HDC_DONOT_FETCH_MEM_WHEN_MASKED);
|
||||
|
||||
/* According to the CACHE_MODE_0 default value documentation, some
|
||||
* CHV platforms disable this optimization by default. Turn it on.
|
||||
*/
|
||||
WA_CLR_BIT_MASKED(CACHE_MODE_0_GEN7, HIZ_RAW_STALL_OPT_DISABLE);
|
||||
|
||||
/* Improve HiZ throughput on CHV. */
|
||||
WA_SET_BIT_MASKED(HIZ_CHICKEN, CHV_HZ_8X8_MODE_IN_1X);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -31,7 +31,6 @@
|
||||
|
||||
#include "i915_drv.h"
|
||||
#include "intel_drv.h"
|
||||
#include <drm/i915_powerwell.h>
|
||||
|
||||
/**
|
||||
* DOC: runtime pm
|
||||
@ -50,8 +49,6 @@
|
||||
* present for a given platform.
|
||||
*/
|
||||
|
||||
static struct i915_power_domains *hsw_pwr;
|
||||
|
||||
#define for_each_power_well(i, power_well, domain_mask, power_domains) \
|
||||
for (i = 0; \
|
||||
i < (power_domains)->power_well_count && \
|
||||
@ -1071,10 +1068,8 @@ int intel_power_domains_init(struct drm_i915_private *dev_priv)
|
||||
*/
|
||||
if (IS_HASWELL(dev_priv->dev)) {
|
||||
set_power_wells(power_domains, hsw_power_wells);
|
||||
hsw_pwr = power_domains;
|
||||
} else if (IS_BROADWELL(dev_priv->dev)) {
|
||||
set_power_wells(power_domains, bdw_power_wells);
|
||||
hsw_pwr = power_domains;
|
||||
} else if (IS_CHERRYVIEW(dev_priv->dev)) {
|
||||
set_power_wells(power_domains, chv_power_wells);
|
||||
} else if (IS_VALLEYVIEW(dev_priv->dev)) {
|
||||
@ -1118,8 +1113,6 @@ void intel_power_domains_fini(struct drm_i915_private *dev_priv)
|
||||
* the power well is not enabled, so just enable it in case
|
||||
* we're going to unload/reload. */
|
||||
intel_display_set_init_power(dev_priv, true);
|
||||
|
||||
hsw_pwr = NULL;
|
||||
}
|
||||
|
||||
static void intel_power_domains_resume(struct drm_i915_private *dev_priv)
|
||||
@ -1328,52 +1321,3 @@ void intel_runtime_pm_enable(struct drm_i915_private *dev_priv)
|
||||
pm_runtime_put_autosuspend(device);
|
||||
}
|
||||
|
||||
/* Display audio driver power well request */
|
||||
int i915_request_power_well(void)
|
||||
{
|
||||
struct drm_i915_private *dev_priv;
|
||||
|
||||
if (!hsw_pwr)
|
||||
return -ENODEV;
|
||||
|
||||
dev_priv = container_of(hsw_pwr, struct drm_i915_private,
|
||||
power_domains);
|
||||
intel_display_power_get(dev_priv, POWER_DOMAIN_AUDIO);
|
||||
return 0;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(i915_request_power_well);
|
||||
|
||||
/* Display audio driver power well release */
|
||||
int i915_release_power_well(void)
|
||||
{
|
||||
struct drm_i915_private *dev_priv;
|
||||
|
||||
if (!hsw_pwr)
|
||||
return -ENODEV;
|
||||
|
||||
dev_priv = container_of(hsw_pwr, struct drm_i915_private,
|
||||
power_domains);
|
||||
intel_display_power_put(dev_priv, POWER_DOMAIN_AUDIO);
|
||||
return 0;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(i915_release_power_well);
|
||||
|
||||
/*
|
||||
* Private interface for the audio driver to get CDCLK in kHz.
|
||||
*
|
||||
* Caller must request power well using i915_request_power_well() prior to
|
||||
* making the call.
|
||||
*/
|
||||
int i915_get_cdclk_freq(void)
|
||||
{
|
||||
struct drm_i915_private *dev_priv;
|
||||
|
||||
if (!hsw_pwr)
|
||||
return -ENODEV;
|
||||
|
||||
dev_priv = container_of(hsw_pwr, struct drm_i915_private,
|
||||
power_domains);
|
||||
|
||||
return intel_ddi_get_cdclk_freq(dev_priv);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(i915_get_cdclk_freq);
|
||||
|
@ -1617,6 +1617,9 @@ static uint16_t intel_sdvo_get_hotplug_support(struct intel_sdvo *intel_sdvo)
|
||||
struct drm_device *dev = intel_sdvo->base.base.dev;
|
||||
uint16_t hotplug;
|
||||
|
||||
if (!I915_HAS_HOTPLUG(dev))
|
||||
return 0;
|
||||
|
||||
/* HW Erratum: SDVO Hotplug is broken on all i945G chips, there's noise
|
||||
* on the line. */
|
||||
if (IS_I945G(dev) || IS_I945GM(dev))
|
||||
|
@ -33,6 +33,7 @@
|
||||
#include <drm/drm_crtc.h>
|
||||
#include <drm/drm_fourcc.h>
|
||||
#include <drm/drm_rect.h>
|
||||
#include <drm/drm_plane_helper.h>
|
||||
#include "intel_drv.h"
|
||||
#include <drm/i915_drm.h>
|
||||
#include "i915_drv.h"
|
||||
@ -412,8 +413,6 @@ vlv_update_plane(struct drm_plane *dplane, struct drm_crtc *crtc,
|
||||
u32 sprctl;
|
||||
unsigned long sprsurf_offset, linear_offset;
|
||||
int pixel_size = drm_format_plane_cpp(fb->pixel_format, 0);
|
||||
u32 start_vbl_count;
|
||||
bool atomic_update;
|
||||
|
||||
sprctl = I915_READ(SPCNTR(pipe, plane));
|
||||
|
||||
@ -502,8 +501,6 @@ vlv_update_plane(struct drm_plane *dplane, struct drm_crtc *crtc,
|
||||
linear_offset += src_h * fb->pitches[0] + src_w * pixel_size;
|
||||
}
|
||||
|
||||
atomic_update = intel_pipe_update_start(intel_crtc, &start_vbl_count);
|
||||
|
||||
intel_update_primary_plane(intel_crtc);
|
||||
|
||||
if (IS_CHERRYVIEW(dev) && pipe == PIPE_B)
|
||||
@ -525,9 +522,6 @@ vlv_update_plane(struct drm_plane *dplane, struct drm_crtc *crtc,
|
||||
sprsurf_offset);
|
||||
|
||||
intel_flush_primary_plane(dev_priv, intel_crtc->plane);
|
||||
|
||||
if (atomic_update)
|
||||
intel_pipe_update_end(intel_crtc, start_vbl_count);
|
||||
}
|
||||
|
||||
static void
|
||||
@ -539,10 +533,6 @@ vlv_disable_plane(struct drm_plane *dplane, struct drm_crtc *crtc)
|
||||
struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
|
||||
int pipe = intel_plane->pipe;
|
||||
int plane = intel_plane->plane;
|
||||
u32 start_vbl_count;
|
||||
bool atomic_update;
|
||||
|
||||
atomic_update = intel_pipe_update_start(intel_crtc, &start_vbl_count);
|
||||
|
||||
intel_update_primary_plane(intel_crtc);
|
||||
|
||||
@ -553,9 +543,6 @@ vlv_disable_plane(struct drm_plane *dplane, struct drm_crtc *crtc)
|
||||
|
||||
intel_flush_primary_plane(dev_priv, intel_crtc->plane);
|
||||
|
||||
if (atomic_update)
|
||||
intel_pipe_update_end(intel_crtc, start_vbl_count);
|
||||
|
||||
intel_update_sprite_watermarks(dplane, crtc, 0, 0, 0, false, false);
|
||||
}
|
||||
|
||||
@ -626,8 +613,6 @@ ivb_update_plane(struct drm_plane *plane, struct drm_crtc *crtc,
|
||||
u32 sprctl, sprscale = 0;
|
||||
unsigned long sprsurf_offset, linear_offset;
|
||||
int pixel_size = drm_format_plane_cpp(fb->pixel_format, 0);
|
||||
u32 start_vbl_count;
|
||||
bool atomic_update;
|
||||
|
||||
sprctl = I915_READ(SPRCTL(pipe));
|
||||
|
||||
@ -711,8 +696,6 @@ ivb_update_plane(struct drm_plane *plane, struct drm_crtc *crtc,
|
||||
}
|
||||
}
|
||||
|
||||
atomic_update = intel_pipe_update_start(intel_crtc, &start_vbl_count);
|
||||
|
||||
intel_update_primary_plane(intel_crtc);
|
||||
|
||||
I915_WRITE(SPRSTRIDE(pipe), fb->pitches[0]);
|
||||
@ -735,9 +718,6 @@ ivb_update_plane(struct drm_plane *plane, struct drm_crtc *crtc,
|
||||
i915_gem_obj_ggtt_offset(obj) + sprsurf_offset);
|
||||
|
||||
intel_flush_primary_plane(dev_priv, intel_crtc->plane);
|
||||
|
||||
if (atomic_update)
|
||||
intel_pipe_update_end(intel_crtc, start_vbl_count);
|
||||
}
|
||||
|
||||
static void
|
||||
@ -748,10 +728,6 @@ ivb_disable_plane(struct drm_plane *plane, struct drm_crtc *crtc)
|
||||
struct intel_plane *intel_plane = to_intel_plane(plane);
|
||||
struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
|
||||
int pipe = intel_plane->pipe;
|
||||
u32 start_vbl_count;
|
||||
bool atomic_update;
|
||||
|
||||
atomic_update = intel_pipe_update_start(intel_crtc, &start_vbl_count);
|
||||
|
||||
intel_update_primary_plane(intel_crtc);
|
||||
|
||||
@ -764,16 +740,12 @@ ivb_disable_plane(struct drm_plane *plane, struct drm_crtc *crtc)
|
||||
|
||||
intel_flush_primary_plane(dev_priv, intel_crtc->plane);
|
||||
|
||||
if (atomic_update)
|
||||
intel_pipe_update_end(intel_crtc, start_vbl_count);
|
||||
|
||||
/*
|
||||
* Avoid underruns when disabling the sprite.
|
||||
* FIXME remove once watermark updates are done properly.
|
||||
*/
|
||||
intel_wait_for_vblank(dev, pipe);
|
||||
|
||||
intel_update_sprite_watermarks(plane, crtc, 0, 0, 0, false, false);
|
||||
intel_crtc->atomic.wait_vblank = true;
|
||||
intel_crtc->atomic.update_sprite_watermarks |= (1 << drm_plane_index(plane));
|
||||
}
|
||||
|
||||
static int
|
||||
@ -846,8 +818,6 @@ ilk_update_plane(struct drm_plane *plane, struct drm_crtc *crtc,
|
||||
unsigned long dvssurf_offset, linear_offset;
|
||||
u32 dvscntr, dvsscale;
|
||||
int pixel_size = drm_format_plane_cpp(fb->pixel_format, 0);
|
||||
u32 start_vbl_count;
|
||||
bool atomic_update;
|
||||
|
||||
dvscntr = I915_READ(DVSCNTR(pipe));
|
||||
|
||||
@ -922,8 +892,6 @@ ilk_update_plane(struct drm_plane *plane, struct drm_crtc *crtc,
|
||||
linear_offset += src_h * fb->pitches[0] + src_w * pixel_size;
|
||||
}
|
||||
|
||||
atomic_update = intel_pipe_update_start(intel_crtc, &start_vbl_count);
|
||||
|
||||
intel_update_primary_plane(intel_crtc);
|
||||
|
||||
I915_WRITE(DVSSTRIDE(pipe), fb->pitches[0]);
|
||||
@ -941,9 +909,6 @@ ilk_update_plane(struct drm_plane *plane, struct drm_crtc *crtc,
|
||||
i915_gem_obj_ggtt_offset(obj) + dvssurf_offset);
|
||||
|
||||
intel_flush_primary_plane(dev_priv, intel_crtc->plane);
|
||||
|
||||
if (atomic_update)
|
||||
intel_pipe_update_end(intel_crtc, start_vbl_count);
|
||||
}
|
||||
|
||||
static void
|
||||
@ -954,10 +919,6 @@ ilk_disable_plane(struct drm_plane *plane, struct drm_crtc *crtc)
|
||||
struct intel_plane *intel_plane = to_intel_plane(plane);
|
||||
struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
|
||||
int pipe = intel_plane->pipe;
|
||||
u32 start_vbl_count;
|
||||
bool atomic_update;
|
||||
|
||||
atomic_update = intel_pipe_update_start(intel_crtc, &start_vbl_count);
|
||||
|
||||
intel_update_primary_plane(intel_crtc);
|
||||
|
||||
@ -969,19 +930,25 @@ ilk_disable_plane(struct drm_plane *plane, struct drm_crtc *crtc)
|
||||
|
||||
intel_flush_primary_plane(dev_priv, intel_crtc->plane);
|
||||
|
||||
if (atomic_update)
|
||||
intel_pipe_update_end(intel_crtc, start_vbl_count);
|
||||
|
||||
/*
|
||||
* Avoid underruns when disabling the sprite.
|
||||
* FIXME remove once watermark updates are done properly.
|
||||
*/
|
||||
intel_wait_for_vblank(dev, pipe);
|
||||
|
||||
intel_update_sprite_watermarks(plane, crtc, 0, 0, 0, false, false);
|
||||
intel_crtc->atomic.wait_vblank = true;
|
||||
intel_crtc->atomic.update_sprite_watermarks |= (1 << drm_plane_index(plane));
|
||||
}
|
||||
|
||||
static void
|
||||
/**
|
||||
* intel_post_enable_primary - Perform operations after enabling primary plane
|
||||
* @crtc: the CRTC whose primary plane was just enabled
|
||||
*
|
||||
* Performs potentially sleeping operations that must be done after the primary
|
||||
* plane is enabled, such as updating FBC and IPS. Note that this may be
|
||||
* called due to an explicit primary plane update, or due to an implicit
|
||||
* re-enable that is caused when a sprite plane is updated to no longer
|
||||
* completely hide the primary plane.
|
||||
*/
|
||||
void
|
||||
intel_post_enable_primary(struct drm_crtc *crtc)
|
||||
{
|
||||
struct drm_device *dev = crtc->dev;
|
||||
@ -1008,7 +975,17 @@ intel_post_enable_primary(struct drm_crtc *crtc)
|
||||
mutex_unlock(&dev->struct_mutex);
|
||||
}
|
||||
|
||||
static void
|
||||
/**
|
||||
* intel_pre_disable_primary - Perform operations before disabling primary plane
|
||||
* @crtc: the CRTC whose primary plane is to be disabled
|
||||
*
|
||||
* Performs potentially sleeping operations that must be done before the
|
||||
* primary plane is enabled, such as updating FBC and IPS. Note that this may
|
||||
* be called due to an explicit primary plane update, or due to an implicit
|
||||
* disable that is caused when a sprite plane completely hides the primary
|
||||
* plane.
|
||||
*/
|
||||
void
|
||||
intel_pre_disable_primary(struct drm_crtc *crtc)
|
||||
{
|
||||
struct drm_device *dev = crtc->dev;
|
||||
@ -1105,15 +1082,16 @@ intel_check_sprite_plane(struct drm_plane *plane,
|
||||
uint32_t src_x, src_y, src_w, src_h;
|
||||
struct drm_rect *src = &state->src;
|
||||
struct drm_rect *dst = &state->dst;
|
||||
struct drm_rect *orig_src = &state->orig_src;
|
||||
const struct drm_rect *clip = &state->clip;
|
||||
int hscale, vscale;
|
||||
int max_scale, min_scale;
|
||||
int pixel_size;
|
||||
|
||||
intel_crtc = intel_crtc ? intel_crtc : to_intel_crtc(plane->crtc);
|
||||
|
||||
if (!fb) {
|
||||
state->visible = false;
|
||||
return 0;
|
||||
goto finish;
|
||||
}
|
||||
|
||||
/* Don't modify another pipe's plane */
|
||||
@ -1191,10 +1169,10 @@ intel_check_sprite_plane(struct drm_plane *plane,
|
||||
intel_plane->rotation);
|
||||
|
||||
/* sanity check to make sure the src viewport wasn't enlarged */
|
||||
WARN_ON(src->x1 < (int) orig_src->x1 ||
|
||||
src->y1 < (int) orig_src->y1 ||
|
||||
src->x2 > (int) orig_src->x2 ||
|
||||
src->y2 > (int) orig_src->y2);
|
||||
WARN_ON(src->x1 < (int) state->base.src_x ||
|
||||
src->y1 < (int) state->base.src_y ||
|
||||
src->x2 > (int) state->base.src_x + state->base.src_w ||
|
||||
src->y2 > (int) state->base.src_y + state->base.src_h);
|
||||
|
||||
/*
|
||||
* Hardware doesn't handle subpixel coordinates.
|
||||
@ -1260,6 +1238,29 @@ intel_check_sprite_plane(struct drm_plane *plane,
|
||||
dst->y1 = crtc_y;
|
||||
dst->y2 = crtc_y + crtc_h;
|
||||
|
||||
finish:
|
||||
/*
|
||||
* If the sprite is completely covering the primary plane,
|
||||
* we can disable the primary and save power.
|
||||
*/
|
||||
state->hides_primary = fb != NULL && drm_rect_equals(dst, clip) &&
|
||||
!colorkey_enabled(intel_plane);
|
||||
WARN_ON(state->hides_primary && !state->visible && intel_crtc->active);
|
||||
|
||||
if (intel_crtc->active) {
|
||||
if (intel_crtc->primary_enabled == state->hides_primary)
|
||||
intel_crtc->atomic.wait_for_flips = true;
|
||||
|
||||
if (intel_crtc->primary_enabled && state->hides_primary)
|
||||
intel_crtc->atomic.pre_disable_primary = true;
|
||||
|
||||
intel_crtc->atomic.fb_bits |=
|
||||
INTEL_FRONTBUFFER_SPRITE(intel_crtc->pipe);
|
||||
|
||||
if (!intel_crtc->primary_enabled && !state->hides_primary)
|
||||
intel_crtc->atomic.post_enable_primary = true;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -1267,58 +1268,23 @@ static void
|
||||
intel_commit_sprite_plane(struct drm_plane *plane,
|
||||
struct intel_plane_state *state)
|
||||
{
|
||||
struct drm_device *dev = plane->dev;
|
||||
struct drm_crtc *crtc = state->base.crtc;
|
||||
struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
|
||||
struct intel_crtc *intel_crtc;
|
||||
struct intel_plane *intel_plane = to_intel_plane(plane);
|
||||
enum pipe pipe = intel_crtc->pipe;
|
||||
struct drm_framebuffer *fb = state->base.fb;
|
||||
struct drm_i915_gem_object *obj = intel_fb_obj(fb);
|
||||
int crtc_x, crtc_y;
|
||||
unsigned int crtc_w, crtc_h;
|
||||
uint32_t src_x, src_y, src_w, src_h;
|
||||
struct drm_rect *dst = &state->dst;
|
||||
const struct drm_rect *clip = &state->clip;
|
||||
bool primary_enabled;
|
||||
|
||||
/*
|
||||
* 'prepare' is never called when plane is being disabled, so we need
|
||||
* to handle frontbuffer tracking here
|
||||
*/
|
||||
if (!fb) {
|
||||
mutex_lock(&dev->struct_mutex);
|
||||
i915_gem_track_fb(intel_fb_obj(plane->fb), NULL,
|
||||
INTEL_FRONTBUFFER_SPRITE(pipe));
|
||||
mutex_unlock(&dev->struct_mutex);
|
||||
}
|
||||
crtc = crtc ? crtc : plane->crtc;
|
||||
intel_crtc = to_intel_crtc(crtc);
|
||||
|
||||
/*
|
||||
* If the sprite is completely covering the primary plane,
|
||||
* we can disable the primary and save power.
|
||||
*/
|
||||
primary_enabled = !drm_rect_equals(dst, clip) || colorkey_enabled(intel_plane);
|
||||
WARN_ON(!primary_enabled && !state->visible && intel_crtc->active);
|
||||
|
||||
intel_plane->crtc_x = state->orig_dst.x1;
|
||||
intel_plane->crtc_y = state->orig_dst.y1;
|
||||
intel_plane->crtc_w = drm_rect_width(&state->orig_dst);
|
||||
intel_plane->crtc_h = drm_rect_height(&state->orig_dst);
|
||||
intel_plane->src_x = state->orig_src.x1;
|
||||
intel_plane->src_y = state->orig_src.y1;
|
||||
intel_plane->src_w = drm_rect_width(&state->orig_src);
|
||||
intel_plane->src_h = drm_rect_height(&state->orig_src);
|
||||
plane->fb = state->base.fb;
|
||||
intel_plane->obj = obj;
|
||||
|
||||
if (intel_crtc->active) {
|
||||
bool primary_was_enabled = intel_crtc->primary_enabled;
|
||||
|
||||
intel_crtc->primary_enabled = primary_enabled;
|
||||
|
||||
if (primary_was_enabled != primary_enabled)
|
||||
intel_crtc_wait_for_pending_flips(crtc);
|
||||
|
||||
if (primary_was_enabled && !primary_enabled)
|
||||
intel_pre_disable_primary(crtc);
|
||||
intel_crtc->primary_enabled = !state->hides_primary;
|
||||
|
||||
if (state->visible) {
|
||||
crtc_x = state->dst.x1;
|
||||
@ -1335,23 +1301,9 @@ intel_commit_sprite_plane(struct drm_plane *plane,
|
||||
} else {
|
||||
intel_plane->disable_plane(plane, crtc);
|
||||
}
|
||||
|
||||
|
||||
intel_frontbuffer_flip(dev, INTEL_FRONTBUFFER_SPRITE(pipe));
|
||||
|
||||
if (!primary_was_enabled && primary_enabled)
|
||||
intel_post_enable_primary(crtc);
|
||||
}
|
||||
}
|
||||
|
||||
static void intel_destroy_plane(struct drm_plane *plane)
|
||||
{
|
||||
struct intel_plane *intel_plane = to_intel_plane(plane);
|
||||
intel_disable_plane(plane);
|
||||
drm_plane_cleanup(plane);
|
||||
kfree(intel_plane);
|
||||
}
|
||||
|
||||
int intel_sprite_set_colorkey(struct drm_device *dev, void *data,
|
||||
struct drm_file *file_priv)
|
||||
{
|
||||
@ -1439,23 +1391,23 @@ int intel_plane_set_property(struct drm_plane *plane,
|
||||
|
||||
int intel_plane_restore(struct drm_plane *plane)
|
||||
{
|
||||
struct intel_plane *intel_plane = to_intel_plane(plane);
|
||||
|
||||
if (!plane->crtc || !plane->fb)
|
||||
return 0;
|
||||
|
||||
return plane->funcs->update_plane(plane, plane->crtc, plane->fb,
|
||||
intel_plane->crtc_x, intel_plane->crtc_y,
|
||||
intel_plane->crtc_w, intel_plane->crtc_h,
|
||||
intel_plane->src_x, intel_plane->src_y,
|
||||
intel_plane->src_w, intel_plane->src_h);
|
||||
plane->state->crtc_x, plane->state->crtc_y,
|
||||
plane->state->crtc_w, plane->state->crtc_h,
|
||||
plane->state->src_x, plane->state->src_y,
|
||||
plane->state->src_w, plane->state->src_h);
|
||||
}
|
||||
|
||||
static const struct drm_plane_funcs intel_plane_funcs = {
|
||||
.update_plane = intel_update_plane,
|
||||
.disable_plane = intel_disable_plane,
|
||||
.destroy = intel_destroy_plane,
|
||||
static const struct drm_plane_funcs intel_sprite_plane_funcs = {
|
||||
.update_plane = drm_plane_helper_update,
|
||||
.disable_plane = drm_plane_helper_disable,
|
||||
.destroy = intel_plane_destroy,
|
||||
.set_property = intel_plane_set_property,
|
||||
.atomic_duplicate_state = intel_plane_duplicate_state,
|
||||
.atomic_destroy_state = intel_plane_destroy_state,
|
||||
};
|
||||
|
||||
static uint32_t ilk_plane_formats[] = {
|
||||
@ -1517,6 +1469,13 @@ intel_plane_init(struct drm_device *dev, enum pipe pipe, int plane)
|
||||
if (!intel_plane)
|
||||
return -ENOMEM;
|
||||
|
||||
intel_plane->base.state =
|
||||
intel_plane_duplicate_state(&intel_plane->base);
|
||||
if (intel_plane->base.state == NULL) {
|
||||
kfree(intel_plane);
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
switch (INTEL_INFO(dev)->gen) {
|
||||
case 5:
|
||||
case 6:
|
||||
@ -1591,7 +1550,7 @@ intel_plane_init(struct drm_device *dev, enum pipe pipe, int plane)
|
||||
intel_plane->commit_plane = intel_commit_sprite_plane;
|
||||
possible_crtcs = (1 << pipe);
|
||||
ret = drm_universal_plane_init(dev, &intel_plane->base, possible_crtcs,
|
||||
&intel_plane_funcs,
|
||||
&intel_sprite_plane_funcs,
|
||||
plane_formats, num_plane_formats,
|
||||
DRM_PLANE_TYPE_OVERLAY);
|
||||
if (ret) {
|
||||
@ -1610,6 +1569,8 @@ intel_plane_init(struct drm_device *dev, enum pipe pipe, int plane)
|
||||
dev->mode_config.rotation_property,
|
||||
intel_plane->rotation);
|
||||
|
||||
drm_plane_helper_add(&intel_plane->base, &intel_plane_helper_funcs);
|
||||
|
||||
out:
|
||||
return ret;
|
||||
}
|
||||
|
38
include/drm/i915_component.h
Normal file
38
include/drm/i915_component.h
Normal file
@ -0,0 +1,38 @@
|
||||
/*
|
||||
* Copyright © 2014 Intel Corporation
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a
|
||||
* copy of this software and associated documentation files (the "Software"),
|
||||
* to deal in the Software without restriction, including without limitation
|
||||
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||
* and/or sell copies of the Software, and to permit persons to whom the
|
||||
* Software is furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice (including the next
|
||||
* paragraph) shall be included in all copies or substantial portions of the
|
||||
* Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
|
||||
* IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#ifndef _I915_COMPONENT_H_
|
||||
#define _I915_COMPONENT_H_
|
||||
|
||||
struct i915_audio_component {
|
||||
struct device *dev;
|
||||
|
||||
const struct i915_audio_component_ops {
|
||||
struct module *owner;
|
||||
void (*get_power)(struct device *);
|
||||
void (*put_power)(struct device *);
|
||||
int (*get_cdclk_freq)(struct device *);
|
||||
} *ops;
|
||||
};
|
||||
|
||||
#endif /* _I915_COMPONENT_H_ */
|
@ -1,37 +0,0 @@
|
||||
/**************************************************************************
|
||||
*
|
||||
* Copyright 2013 Intel Inc.
|
||||
* All Rights Reserved.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a
|
||||
* copy of this software and associated documentation files (the
|
||||
* "Software"), to deal in the Software without restriction, including
|
||||
* without limitation the rights to use, copy, modify, merge, publish,
|
||||
* distribute, sub license, and/or sell copies of the Software, and to
|
||||
* permit persons to whom the Software is furnished to do so, subject to
|
||||
* the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice (including the
|
||||
* next paragraph) shall be included in all copies or substantial portions
|
||||
* of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
|
||||
* THE COPYRIGHT HOLDERS, AUTHORS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM,
|
||||
* DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
|
||||
* OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
|
||||
* USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*
|
||||
*
|
||||
**************************************************************************/
|
||||
|
||||
#ifndef _I915_POWERWELL_H_
|
||||
#define _I915_POWERWELL_H_
|
||||
|
||||
/* For use by hda_i915 driver */
|
||||
extern int i915_request_power_well(void);
|
||||
extern int i915_release_power_well(void);
|
||||
extern int i915_get_cdclk_freq(void);
|
||||
|
||||
#endif /* _I915_POWERWELL_H_ */
|
@ -224,6 +224,8 @@ typedef struct _drm_i915_sarea {
|
||||
#define DRM_I915_REG_READ 0x31
|
||||
#define DRM_I915_GET_RESET_STATS 0x32
|
||||
#define DRM_I915_GEM_USERPTR 0x33
|
||||
#define DRM_I915_GEM_CONTEXT_GETPARAM 0x34
|
||||
#define DRM_I915_GEM_CONTEXT_SETPARAM 0x35
|
||||
|
||||
#define DRM_IOCTL_I915_INIT DRM_IOW( DRM_COMMAND_BASE + DRM_I915_INIT, drm_i915_init_t)
|
||||
#define DRM_IOCTL_I915_FLUSH DRM_IO ( DRM_COMMAND_BASE + DRM_I915_FLUSH)
|
||||
@ -275,6 +277,8 @@ typedef struct _drm_i915_sarea {
|
||||
#define DRM_IOCTL_I915_REG_READ DRM_IOWR (DRM_COMMAND_BASE + DRM_I915_REG_READ, struct drm_i915_reg_read)
|
||||
#define DRM_IOCTL_I915_GET_RESET_STATS DRM_IOWR (DRM_COMMAND_BASE + DRM_I915_GET_RESET_STATS, struct drm_i915_reset_stats)
|
||||
#define DRM_IOCTL_I915_GEM_USERPTR DRM_IOWR (DRM_COMMAND_BASE + DRM_I915_GEM_USERPTR, struct drm_i915_gem_userptr)
|
||||
#define DRM_IOCTL_I915_GEM_CONTEXT_GETPARAM DRM_IOWR (DRM_COMMAND_BASE + DRM_I915_GEM_CONTEXT_GETPARAM, struct drm_i915_gem_context_param)
|
||||
#define DRM_IOCTL_I915_GEM_CONTEXT_SETPARAM DRM_IOWR (DRM_COMMAND_BASE + DRM_I915_GEM_CONTEXT_SETPARAM, struct drm_i915_gem_context_param)
|
||||
|
||||
/* Allow drivers to submit batchbuffers directly to hardware, relying
|
||||
* on the security mechanisms provided by hardware.
|
||||
@ -341,6 +345,7 @@ typedef struct drm_i915_irq_wait {
|
||||
#define I915_PARAM_HAS_WT 27
|
||||
#define I915_PARAM_CMD_PARSER_VERSION 28
|
||||
#define I915_PARAM_HAS_COHERENT_PHYS_GTT 29
|
||||
#define I915_PARAM_MMAP_VERSION 30
|
||||
|
||||
typedef struct drm_i915_getparam {
|
||||
int param;
|
||||
@ -488,6 +493,14 @@ struct drm_i915_gem_mmap {
|
||||
* This is a fixed-size type for 32/64 compatibility.
|
||||
*/
|
||||
__u64 addr_ptr;
|
||||
|
||||
/**
|
||||
* Flags for extended behaviour.
|
||||
*
|
||||
* Added in version 2.
|
||||
*/
|
||||
__u64 flags;
|
||||
#define I915_MMAP_WC 0x1
|
||||
};
|
||||
|
||||
struct drm_i915_gem_mmap_gtt {
|
||||
@ -1073,4 +1086,12 @@ struct drm_i915_gem_userptr {
|
||||
__u32 handle;
|
||||
};
|
||||
|
||||
struct drm_i915_gem_context_param {
|
||||
__u32 ctx_id;
|
||||
__u32 size;
|
||||
__u64 param;
|
||||
#define I915_CONTEXT_PARAM_BAN_PERIOD 0x1
|
||||
__u64 value;
|
||||
};
|
||||
|
||||
#endif /* _UAPI_I915_DRM_H_ */
|
||||
|
@ -18,10 +18,12 @@
|
||||
|
||||
#include <linux/init.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/pci.h>
|
||||
#include <linux/component.h>
|
||||
#include <drm/i915_component.h>
|
||||
#include <sound/core.h>
|
||||
#include <drm/i915_powerwell.h>
|
||||
#include "hda_priv.h"
|
||||
#include "hda_i915.h"
|
||||
#include "hda_intel.h"
|
||||
|
||||
/* Intel HSW/BDW display HDA controller Extended Mode registers.
|
||||
* EM4 (M value) and EM5 (N Value) are used to convert CDClk (Core Display
|
||||
@ -31,32 +33,33 @@
|
||||
#define AZX_REG_EM4 0x100c
|
||||
#define AZX_REG_EM5 0x1010
|
||||
|
||||
static int (*get_power)(void);
|
||||
static int (*put_power)(void);
|
||||
static int (*get_cdclk)(void);
|
||||
|
||||
int hda_display_power(bool enable)
|
||||
int hda_display_power(struct hda_intel *hda, bool enable)
|
||||
{
|
||||
if (!get_power || !put_power)
|
||||
struct i915_audio_component *acomp = &hda->audio_component;
|
||||
|
||||
if (!acomp->ops)
|
||||
return -ENODEV;
|
||||
|
||||
pr_debug("HDA display power %s \n",
|
||||
enable ? "Enable" : "Disable");
|
||||
dev_dbg(&hda->chip.pci->dev, "display power %s\n",
|
||||
enable ? "enable" : "disable");
|
||||
if (enable)
|
||||
return get_power();
|
||||
acomp->ops->get_power(acomp->dev);
|
||||
else
|
||||
return put_power();
|
||||
acomp->ops->put_power(acomp->dev);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void haswell_set_bclk(struct azx *chip)
|
||||
void haswell_set_bclk(struct hda_intel *hda)
|
||||
{
|
||||
int cdclk_freq;
|
||||
unsigned int bclk_m, bclk_n;
|
||||
struct i915_audio_component *acomp = &hda->audio_component;
|
||||
|
||||
if (!get_cdclk)
|
||||
if (!acomp->ops)
|
||||
return;
|
||||
|
||||
cdclk_freq = get_cdclk();
|
||||
cdclk_freq = acomp->ops->get_cdclk_freq(acomp->dev);
|
||||
switch (cdclk_freq) {
|
||||
case 337500:
|
||||
bclk_m = 16;
|
||||
@ -80,51 +83,108 @@ void haswell_set_bclk(struct azx *chip)
|
||||
break;
|
||||
}
|
||||
|
||||
azx_writew(chip, EM4, bclk_m);
|
||||
azx_writew(chip, EM5, bclk_n);
|
||||
azx_writew(&hda->chip, EM4, bclk_m);
|
||||
azx_writew(&hda->chip, EM5, bclk_n);
|
||||
}
|
||||
|
||||
|
||||
int hda_i915_init(void)
|
||||
static int hda_component_master_bind(struct device *dev)
|
||||
{
|
||||
int err = 0;
|
||||
struct snd_card *card = dev_get_drvdata(dev);
|
||||
struct azx *chip = card->private_data;
|
||||
struct hda_intel *hda = container_of(chip, struct hda_intel, chip);
|
||||
struct i915_audio_component *acomp = &hda->audio_component;
|
||||
int ret;
|
||||
|
||||
get_power = symbol_request(i915_request_power_well);
|
||||
if (!get_power) {
|
||||
pr_warn("hda-i915: get_power symbol get fail\n");
|
||||
return -ENODEV;
|
||||
ret = component_bind_all(dev, acomp);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
if (WARN_ON(!(acomp->dev && acomp->ops && acomp->ops->get_power &&
|
||||
acomp->ops->put_power && acomp->ops->get_cdclk_freq))) {
|
||||
ret = -EINVAL;
|
||||
goto out_unbind;
|
||||
}
|
||||
|
||||
put_power = symbol_request(i915_release_power_well);
|
||||
if (!put_power) {
|
||||
symbol_put(i915_request_power_well);
|
||||
get_power = NULL;
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
get_cdclk = symbol_request(i915_get_cdclk_freq);
|
||||
if (!get_cdclk) /* may have abnormal BCLK and audio playback rate */
|
||||
pr_warn("hda-i915: get_cdclk symbol get fail\n");
|
||||
|
||||
pr_debug("HDA driver get symbol successfully from i915 module\n");
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
int hda_i915_exit(void)
|
||||
{
|
||||
if (get_power) {
|
||||
symbol_put(i915_request_power_well);
|
||||
get_power = NULL;
|
||||
}
|
||||
if (put_power) {
|
||||
symbol_put(i915_release_power_well);
|
||||
put_power = NULL;
|
||||
}
|
||||
if (get_cdclk) {
|
||||
symbol_put(i915_get_cdclk_freq);
|
||||
get_cdclk = NULL;
|
||||
/*
|
||||
* Atm, we don't support dynamic unbinding initiated by the child
|
||||
* component, so pin its containing module until we unbind.
|
||||
*/
|
||||
if (!try_module_get(acomp->ops->owner)) {
|
||||
ret = -ENODEV;
|
||||
goto out_unbind;
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
||||
out_unbind:
|
||||
component_unbind_all(dev, acomp);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void hda_component_master_unbind(struct device *dev)
|
||||
{
|
||||
struct snd_card *card = dev_get_drvdata(dev);
|
||||
struct azx *chip = card->private_data;
|
||||
struct hda_intel *hda = container_of(chip, struct hda_intel, chip);
|
||||
struct i915_audio_component *acomp = &hda->audio_component;
|
||||
|
||||
module_put(acomp->ops->owner);
|
||||
component_unbind_all(dev, acomp);
|
||||
WARN_ON(acomp->ops || acomp->dev);
|
||||
}
|
||||
|
||||
static const struct component_master_ops hda_component_master_ops = {
|
||||
.bind = hda_component_master_bind,
|
||||
.unbind = hda_component_master_unbind,
|
||||
};
|
||||
|
||||
static int hda_component_master_match(struct device *dev, void *data)
|
||||
{
|
||||
/* i915 is the only supported component */
|
||||
return !strcmp(dev->driver->name, "i915");
|
||||
}
|
||||
|
||||
int hda_i915_init(struct hda_intel *hda)
|
||||
{
|
||||
struct component_match *match = NULL;
|
||||
struct device *dev = &hda->chip.pci->dev;
|
||||
struct i915_audio_component *acomp = &hda->audio_component;
|
||||
int ret;
|
||||
|
||||
component_match_add(dev, &match, hda_component_master_match, hda);
|
||||
ret = component_master_add_with_match(dev, &hda_component_master_ops,
|
||||
match);
|
||||
if (ret < 0)
|
||||
goto out_err;
|
||||
|
||||
/*
|
||||
* Atm, we don't support deferring the component binding, so make sure
|
||||
* i915 is loaded and that the binding successfully completes.
|
||||
*/
|
||||
request_module("i915");
|
||||
|
||||
if (!acomp->ops) {
|
||||
ret = -ENODEV;
|
||||
goto out_master_del;
|
||||
}
|
||||
|
||||
dev_dbg(dev, "bound to i915 component master\n");
|
||||
|
||||
return 0;
|
||||
out_master_del:
|
||||
component_master_del(dev, &hda_component_master_ops);
|
||||
out_err:
|
||||
dev_err(dev, "failed to add i915 component master (%d)\n", ret);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
int hda_i915_exit(struct hda_intel *hda)
|
||||
{
|
||||
struct device *dev = &hda->chip.pci->dev;
|
||||
|
||||
component_master_del(dev, &hda_component_master_ops);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -1,37 +0,0 @@
|
||||
/*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License as published by the Free
|
||||
* Software Foundation; either version 2 of the License, or (at your option)
|
||||
* any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
|
||||
* more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along with
|
||||
* this program; if not, write to the Free Software Foundation, Inc., 59
|
||||
* Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
*/
|
||||
#ifndef __SOUND_HDA_I915_H
|
||||
#define __SOUND_HDA_I915_H
|
||||
|
||||
#ifdef CONFIG_SND_HDA_I915
|
||||
int hda_display_power(bool enable);
|
||||
void haswell_set_bclk(struct azx *chip);
|
||||
int hda_i915_init(void);
|
||||
int hda_i915_exit(void);
|
||||
#else
|
||||
static inline int hda_display_power(bool enable) { return 0; }
|
||||
static inline void haswell_set_bclk(struct azx *chip) { return; }
|
||||
static inline int hda_i915_init(void)
|
||||
{
|
||||
return -ENODEV;
|
||||
}
|
||||
static inline int hda_i915_exit(void)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
@ -63,7 +63,7 @@
|
||||
#include "hda_codec.h"
|
||||
#include "hda_controller.h"
|
||||
#include "hda_priv.h"
|
||||
#include "hda_i915.h"
|
||||
#include "hda_intel.h"
|
||||
|
||||
/* position fix mode */
|
||||
enum {
|
||||
@ -354,31 +354,6 @@ static char *driver_short_names[] = {
|
||||
[AZX_DRIVER_GENERIC] = "HD-Audio Generic",
|
||||
};
|
||||
|
||||
struct hda_intel {
|
||||
struct azx chip;
|
||||
|
||||
/* for pending irqs */
|
||||
struct work_struct irq_pending_work;
|
||||
|
||||
/* sync probing */
|
||||
struct completion probe_wait;
|
||||
struct work_struct probe_work;
|
||||
|
||||
/* card list (for power_save trigger) */
|
||||
struct list_head list;
|
||||
|
||||
/* extra flags */
|
||||
unsigned int irq_pending_warned:1;
|
||||
|
||||
/* VGA-switcheroo setup */
|
||||
unsigned int use_vga_switcheroo:1;
|
||||
unsigned int vga_switcheroo_registered:1;
|
||||
unsigned int init_failed:1; /* delayed init failed */
|
||||
|
||||
/* secondary power domain for hdmi audio under vga device */
|
||||
struct dev_pm_domain hdmi_pm_domain;
|
||||
};
|
||||
|
||||
#ifdef CONFIG_X86
|
||||
static void __mark_pages_wc(struct azx *chip, struct snd_dma_buffer *dmab, bool on)
|
||||
{
|
||||
@ -828,7 +803,7 @@ static int azx_suspend(struct device *dev)
|
||||
pci_save_state(pci);
|
||||
pci_set_power_state(pci, PCI_D3hot);
|
||||
if (chip->driver_caps & AZX_DCAPS_I915_POWERWELL)
|
||||
hda_display_power(false);
|
||||
hda_display_power(hda, false);
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -848,8 +823,8 @@ static int azx_resume(struct device *dev)
|
||||
return 0;
|
||||
|
||||
if (chip->driver_caps & AZX_DCAPS_I915_POWERWELL) {
|
||||
hda_display_power(true);
|
||||
haswell_set_bclk(chip);
|
||||
hda_display_power(hda, true);
|
||||
haswell_set_bclk(hda);
|
||||
}
|
||||
pci_set_power_state(pci, PCI_D0);
|
||||
pci_restore_state(pci);
|
||||
@ -901,7 +876,7 @@ static int azx_runtime_suspend(struct device *dev)
|
||||
azx_enter_link_reset(chip);
|
||||
azx_clear_irq_pending(chip);
|
||||
if (chip->driver_caps & AZX_DCAPS_I915_POWERWELL)
|
||||
hda_display_power(false);
|
||||
hda_display_power(hda, false);
|
||||
|
||||
return 0;
|
||||
}
|
||||
@ -927,8 +902,8 @@ static int azx_runtime_resume(struct device *dev)
|
||||
return 0;
|
||||
|
||||
if (chip->driver_caps & AZX_DCAPS_I915_POWERWELL) {
|
||||
hda_display_power(true);
|
||||
haswell_set_bclk(chip);
|
||||
hda_display_power(hda, true);
|
||||
haswell_set_bclk(hda);
|
||||
}
|
||||
|
||||
/* Read STATESTS before controller reset */
|
||||
@ -1150,8 +1125,8 @@ static int azx_free(struct azx *chip)
|
||||
release_firmware(chip->fw);
|
||||
#endif
|
||||
if (chip->driver_caps & AZX_DCAPS_I915_POWERWELL) {
|
||||
hda_display_power(false);
|
||||
hda_i915_exit();
|
||||
hda_display_power(hda, false);
|
||||
hda_i915_exit(hda);
|
||||
}
|
||||
kfree(hda);
|
||||
|
||||
@ -1629,8 +1604,12 @@ static int azx_first_init(struct azx *chip)
|
||||
/* initialize chip */
|
||||
azx_init_pci(chip);
|
||||
|
||||
if (chip->driver_caps & AZX_DCAPS_I915_POWERWELL)
|
||||
haswell_set_bclk(chip);
|
||||
if (chip->driver_caps & AZX_DCAPS_I915_POWERWELL) {
|
||||
struct hda_intel *hda;
|
||||
|
||||
hda = container_of(chip, struct hda_intel, chip);
|
||||
haswell_set_bclk(hda);
|
||||
}
|
||||
|
||||
azx_init_chip(chip, (probe_only[dev] & 2) == 0);
|
||||
|
||||
@ -1910,13 +1889,10 @@ static int azx_probe_continue(struct azx *chip)
|
||||
/* Request power well for Haswell HDA controller and codec */
|
||||
if (chip->driver_caps & AZX_DCAPS_I915_POWERWELL) {
|
||||
#ifdef CONFIG_SND_HDA_I915
|
||||
err = hda_i915_init();
|
||||
if (err < 0) {
|
||||
dev_err(chip->card->dev,
|
||||
"Error request power-well from i915\n");
|
||||
err = hda_i915_init(hda);
|
||||
if (err < 0)
|
||||
goto out_free;
|
||||
}
|
||||
err = hda_display_power(true);
|
||||
err = hda_display_power(hda, true);
|
||||
if (err < 0) {
|
||||
dev_err(chip->card->dev,
|
||||
"Cannot turn on display power on i915\n");
|
||||
|
71
sound/pci/hda/hda_intel.h
Normal file
71
sound/pci/hda/hda_intel.h
Normal file
@ -0,0 +1,71 @@
|
||||
/*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License as published by the Free
|
||||
* Software Foundation; either version 2 of the License, or (at your option)
|
||||
* any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
|
||||
* more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along with
|
||||
* this program; if not, write to the Free Software Foundation, Inc., 59
|
||||
* Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
*/
|
||||
#ifndef __SOUND_HDA_INTEL_H
|
||||
#define __SOUND_HDA_INTEL_H
|
||||
|
||||
#include <drm/i915_component.h>
|
||||
#include "hda_priv.h"
|
||||
|
||||
struct hda_intel {
|
||||
struct azx chip;
|
||||
|
||||
/* for pending irqs */
|
||||
struct work_struct irq_pending_work;
|
||||
|
||||
/* sync probing */
|
||||
struct completion probe_wait;
|
||||
struct work_struct probe_work;
|
||||
|
||||
/* card list (for power_save trigger) */
|
||||
struct list_head list;
|
||||
|
||||
/* extra flags */
|
||||
unsigned int irq_pending_warned:1;
|
||||
|
||||
/* VGA-switcheroo setup */
|
||||
unsigned int use_vga_switcheroo:1;
|
||||
unsigned int vga_switcheroo_registered:1;
|
||||
unsigned int init_failed:1; /* delayed init failed */
|
||||
|
||||
/* secondary power domain for hdmi audio under vga device */
|
||||
struct dev_pm_domain hdmi_pm_domain;
|
||||
|
||||
/* i915 component interface */
|
||||
struct i915_audio_component audio_component;
|
||||
};
|
||||
|
||||
#ifdef CONFIG_SND_HDA_I915
|
||||
int hda_display_power(struct hda_intel *hda, bool enable);
|
||||
void haswell_set_bclk(struct hda_intel *hda);
|
||||
int hda_i915_init(struct hda_intel *hda);
|
||||
int hda_i915_exit(struct hda_intel *hda);
|
||||
#else
|
||||
static inline int hda_display_power(struct hda_intel *hda, bool enable)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
static inline void haswell_set_bclk(struct hda_intel *hda) { return; }
|
||||
static inline int hda_i915_init(struct hda_intel *hda)
|
||||
{
|
||||
return -ENODEV;
|
||||
}
|
||||
static inline int hda_i915_exit(struct hda_intel *hda)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
Loading…
Reference in New Issue
Block a user