summaryrefslogtreecommitdiff
path: root/drivers/gpu/drm/i915
diff options
context:
space:
mode:
authorDaniel Vetter <daniel.vetter@ffwll.ch>2017-03-08 10:54:45 +0100
committerDaniel Vetter <daniel.vetter@ffwll.ch>2017-03-08 10:54:45 +0100
commit7ffe939dd9c71e149f31817394b70b52b4067304 (patch)
treed779769f1477be9b9976699d6778a45edd001e4a /drivers/gpu/drm/i915
parent7c55e2c5772dcf3cbacd0fa2bcfeefae416b73f7 (diff)
parent6796b129b0e98162a84e0b6322ac28587556d427 (diff)
Merge remote-tracking branch 'airlied/drm-next' into drm-intel-next-queued
Backmerge drm-next to get at all the good stuff in drm-misc. We need that because: - drm_connector_list_iter conversion for i915 needs the core patches. - Maarten's patches to use the new atomic state iterators also need the core patches. - We need the new link status property to complete the DP retraining work, merging through 2 branches wasn't a good idea and we had to partially backtrack. - Chris needs reservation_object_trylock and we want to roll out kref_read everywhere. Signed-off-by: Daniel Vetter <daniel.vetter@intel.com>
Diffstat (limited to 'drivers/gpu/drm/i915')
-rw-r--r--drivers/gpu/drm/i915/Makefile3
-rw-r--r--drivers/gpu/drm/i915/i915_debugfs.c97
-rw-r--r--drivers/gpu/drm/i915/i915_drv.c5
-rw-r--r--drivers/gpu/drm/i915/i915_drv.h18
-rw-r--r--drivers/gpu/drm/i915/i915_gem.c4
-rw-r--r--drivers/gpu/drm/i915/i915_gem_dmabuf.c2
-rw-r--r--drivers/gpu/drm/i915/i915_gem_object.h2
-rw-r--r--drivers/gpu/drm/i915/i915_gem_render_state.c2
-rw-r--r--drivers/gpu/drm/i915/i915_gem_request.c3
-rw-r--r--drivers/gpu/drm/i915/i915_gem_userptr.c5
-rw-r--r--drivers/gpu/drm/i915/i915_irq.c17
-rw-r--r--drivers/gpu/drm/i915/i915_reg.h16
-rw-r--r--drivers/gpu/drm/i915/i915_sw_fence.c8
-rw-r--r--drivers/gpu/drm/i915/intel_audio.c63
-rw-r--r--drivers/gpu/drm/i915/intel_breadcrumbs.c1
-rw-r--r--drivers/gpu/drm/i915/intel_display.c13
-rw-r--r--drivers/gpu/drm/i915/intel_drv.h4
-rw-r--r--drivers/gpu/drm/i915/intel_fbdev.c5
-rw-r--r--drivers/gpu/drm/i915/intel_hdmi.c1
-rw-r--r--drivers/gpu/drm/i915/intel_lpe_audio.c392
-rw-r--r--drivers/gpu/drm/i915/intel_pipe_crc.c68
21 files changed, 548 insertions, 181 deletions
diff --git a/drivers/gpu/drm/i915/Makefile b/drivers/gpu/drm/i915/Makefile
index aa1ba1df96a2..2cf04504e494 100644
--- a/drivers/gpu/drm/i915/Makefile
+++ b/drivers/gpu/drm/i915/Makefile
@@ -134,6 +134,9 @@ i915-y += intel_gvt.o
include $(src)/gvt/Makefile
endif
+# LPE Audio for VLV and CHT
+i915-y += intel_lpe_audio.o
+
obj-$(CONFIG_DRM_I915) += i915.o
CFLAGS_i915_trace_points.o := -I$(src)
diff --git a/drivers/gpu/drm/i915/i915_debugfs.c b/drivers/gpu/drm/i915/i915_debugfs.c
index 32340202dd47..3a2ef08ed3a1 100644
--- a/drivers/gpu/drm/i915/i915_debugfs.c
+++ b/drivers/gpu/drm/i915/i915_debugfs.c
@@ -35,32 +35,6 @@ static inline struct drm_i915_private *node_to_i915(struct drm_info_node *node)
return to_i915(node->minor->dev);
}
-/* As the drm_debugfs_init() routines are called before dev->dev_private is
- * allocated we need to hook into the minor for release. */
-static int
-drm_add_fake_info_node(struct drm_minor *minor,
- struct dentry *ent,
- const void *key)
-{
- struct drm_info_node *node;
-
- node = kmalloc(sizeof(*node), GFP_KERNEL);
- if (node == NULL) {
- debugfs_remove(ent);
- return -ENOMEM;
- }
-
- node->minor = minor;
- node->dent = ent;
- node->info_ent = (void *)key;
-
- mutex_lock(&minor->debugfs_lock);
- list_add(&node->list, &minor->debugfs_list);
- mutex_unlock(&minor->debugfs_lock);
-
- return 0;
-}
-
static __always_inline void seq_print_param(struct seq_file *m,
const char *name,
const char *type,
@@ -4671,20 +4645,6 @@ static const struct file_operations i915_forcewake_fops = {
.release = i915_forcewake_release,
};
-static int i915_forcewake_create(struct dentry *root, struct drm_minor *minor)
-{
- struct dentry *ent;
-
- ent = debugfs_create_file("i915_forcewake_user",
- S_IRUSR,
- root, to_i915(minor->dev),
- &i915_forcewake_fops);
- if (!ent)
- return -ENOMEM;
-
- return drm_add_fake_info_node(minor, ent, &i915_forcewake_fops);
-}
-
static int i915_hpd_storm_ctl_show(struct seq_file *m, void *data)
{
struct drm_i915_private *dev_priv = m->private;
@@ -4760,23 +4720,6 @@ static const struct file_operations i915_hpd_storm_ctl_fops = {
.write = i915_hpd_storm_ctl_write
};
-static int i915_debugfs_create(struct dentry *root,
- struct drm_minor *minor,
- const char *name,
- const struct file_operations *fops)
-{
- struct dentry *ent;
-
- ent = debugfs_create_file(name,
- S_IRUGO | S_IWUSR,
- root, to_i915(minor->dev),
- fops);
- if (!ent)
- return -ENOMEM;
-
- return drm_add_fake_info_node(minor, ent, fops);
-}
-
static const struct drm_info_list i915_debugfs_list[] = {
{"i915_capabilities", i915_capabilities, 0},
{"i915_gem_objects", i915_gem_object_info, 0},
@@ -4861,22 +4804,27 @@ static const struct i915_debugfs_files {
int i915_debugfs_register(struct drm_i915_private *dev_priv)
{
struct drm_minor *minor = dev_priv->drm.primary;
+ struct dentry *ent;
int ret, i;
- ret = i915_forcewake_create(minor->debugfs_root, minor);
- if (ret)
- return ret;
+ ent = debugfs_create_file("i915_forcewake_user", S_IRUSR,
+ minor->debugfs_root, to_i915(minor->dev),
+ &i915_forcewake_fops);
+ if (!ent)
+ return -ENOMEM;
ret = intel_pipe_crc_create(minor);
if (ret)
return ret;
for (i = 0; i < ARRAY_SIZE(i915_debugfs_files); i++) {
- ret = i915_debugfs_create(minor->debugfs_root, minor,
- i915_debugfs_files[i].name,
+ ent = debugfs_create_file(i915_debugfs_files[i].name,
+ S_IRUGO | S_IWUSR,
+ minor->debugfs_root,
+ to_i915(minor->dev),
i915_debugfs_files[i].fops);
- if (ret)
- return ret;
+ if (!ent)
+ return -ENOMEM;
}
return drm_debugfs_create_files(i915_debugfs_list,
@@ -4884,27 +4832,6 @@ int i915_debugfs_register(struct drm_i915_private *dev_priv)
minor->debugfs_root, minor);
}
-void i915_debugfs_unregister(struct drm_i915_private *dev_priv)
-{
- struct drm_minor *minor = dev_priv->drm.primary;
- int i;
-
- drm_debugfs_remove_files(i915_debugfs_list,
- I915_DEBUGFS_ENTRIES, minor);
-
- drm_debugfs_remove_files((struct drm_info_list *)&i915_forcewake_fops,
- 1, minor);
-
- intel_pipe_crc_cleanup(minor);
-
- for (i = 0; i < ARRAY_SIZE(i915_debugfs_files); i++) {
- struct drm_info_list *info_list =
- (struct drm_info_list *)i915_debugfs_files[i].fops;
-
- drm_debugfs_remove_files(info_list, 1, minor);
- }
-}
-
struct dpcd_block {
/* DPCD dump start address. */
unsigned int offset;
diff --git a/drivers/gpu/drm/i915/i915_drv.c b/drivers/gpu/drm/i915/i915_drv.c
index 9be9b9b7f9cb..704dbcf63866 100644
--- a/drivers/gpu/drm/i915/i915_drv.c
+++ b/drivers/gpu/drm/i915/i915_drv.c
@@ -1163,7 +1163,7 @@ static void i915_driver_register(struct drm_i915_private *dev_priv)
if (IS_GEN5(dev_priv))
intel_gpu_ips_init(dev_priv);
- i915_audio_component_init(dev_priv);
+ intel_audio_init(dev_priv);
/*
* Some ports require correctly set-up hpd registers for detection to
@@ -1181,7 +1181,7 @@ static void i915_driver_register(struct drm_i915_private *dev_priv)
*/
static void i915_driver_unregister(struct drm_i915_private *dev_priv)
{
- i915_audio_component_cleanup(dev_priv);
+ intel_audio_deinit(dev_priv);
intel_gpu_ips_teardown();
acpi_video_unregister();
@@ -1191,7 +1191,6 @@ static void i915_driver_unregister(struct drm_i915_private *dev_priv)
i915_teardown_sysfs(dev_priv);
i915_guc_log_unregister(dev_priv);
- i915_debugfs_unregister(dev_priv);
drm_dev_unregister(&dev_priv->drm);
i915_gem_shrinker_cleanup(dev_priv);
diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h
index 937534897d21..ceb47a7ab713 100644
--- a/drivers/gpu/drm/i915/i915_drv.h
+++ b/drivers/gpu/drm/i915/i915_drv.h
@@ -2518,6 +2518,12 @@ struct drm_i915_private {
/* Used to save the pipe-to-encoder mapping for audio */
struct intel_encoder *av_enc_map[I915_MAX_PIPES];
+ /* necessary resource sharing with HDMI LPE audio driver. */
+ struct {
+ struct platform_device *platdev;
+ int irq;
+ } lpe_audio;
+
/*
* NOTE: This is the dri1/ums dungeon, don't add stuff here. Your patch
* will be rejected. Instead look for a better place.
@@ -3416,7 +3422,7 @@ int i915_gem_wait_for_idle(struct drm_i915_private *dev_priv,
unsigned int flags);
int __must_check i915_gem_suspend(struct drm_i915_private *dev_priv);
void i915_gem_resume(struct drm_i915_private *dev_priv);
-int i915_gem_fault(struct vm_area_struct *vma, struct vm_fault *vmf);
+int i915_gem_fault(struct vm_fault *vmf);
int i915_gem_object_wait(struct drm_i915_gem_object *obj,
unsigned int flags,
long timeout,
@@ -3592,12 +3598,10 @@ u32 i915_gem_fence_alignment(struct drm_i915_private *dev_priv, u32 size,
/* i915_debugfs.c */
#ifdef CONFIG_DEBUG_FS
int i915_debugfs_register(struct drm_i915_private *dev_priv);
-void i915_debugfs_unregister(struct drm_i915_private *dev_priv);
int i915_debugfs_connector_add(struct drm_connector *connector);
void intel_display_crc_init(struct drm_i915_private *dev_priv);
#else
static inline int i915_debugfs_register(struct drm_i915_private *dev_priv) {return 0;}
-static inline void i915_debugfs_unregister(struct drm_i915_private *dev_priv) {}
static inline int i915_debugfs_connector_add(struct drm_connector *connector)
{ return 0; }
static inline void intel_display_crc_init(struct drm_i915_private *dev_priv) {}
@@ -3688,6 +3692,14 @@ extern int i915_restore_state(struct drm_i915_private *dev_priv);
void i915_setup_sysfs(struct drm_i915_private *dev_priv);
void i915_teardown_sysfs(struct drm_i915_private *dev_priv);
+/* intel_lpe_audio.c */
+int intel_lpe_audio_init(struct drm_i915_private *dev_priv);
+void intel_lpe_audio_teardown(struct drm_i915_private *dev_priv);
+void intel_lpe_audio_irq_handler(struct drm_i915_private *dev_priv);
+void intel_lpe_audio_notify(struct drm_i915_private *dev_priv,
+ void *eld, int port, int pipe, int tmds_clk_speed,
+ bool dp_output, int link_rate);
+
/* intel_i2c.c */
extern int intel_setup_gmbus(struct drm_i915_private *dev_priv);
extern void intel_teardown_gmbus(struct drm_i915_private *dev_priv);
diff --git a/drivers/gpu/drm/i915/i915_gem.c b/drivers/gpu/drm/i915/i915_gem.c
index b2beb02c0cae..e29f9400c9d1 100644
--- a/drivers/gpu/drm/i915/i915_gem.c
+++ b/drivers/gpu/drm/i915/i915_gem.c
@@ -1789,7 +1789,6 @@ compute_partial_view(struct drm_i915_gem_object *obj,
/**
* i915_gem_fault - fault a page into the GTT
- * @area: CPU VMA in question
* @vmf: fault info
*
* The fault handler is set up by drm_gem_mmap() when a object is GTT mapped
@@ -1806,9 +1805,10 @@ compute_partial_view(struct drm_i915_gem_object *obj,
* The current feature set supported by i915_gem_fault() and thus GTT mmaps
* is exposed via I915_PARAM_MMAP_GTT_VERSION (see i915_gem_mmap_gtt_version).
*/
-int i915_gem_fault(struct vm_area_struct *area, struct vm_fault *vmf)
+int i915_gem_fault(struct vm_fault *vmf)
{
#define MIN_CHUNK_PAGES ((1 << 20) >> PAGE_SHIFT) /* 1 MiB */
+ struct vm_area_struct *area = vmf->vma;
struct drm_i915_gem_object *obj = to_intel_bo(area->vm_private_data);
struct drm_device *dev = obj->base.dev;
struct drm_i915_private *dev_priv = to_i915(dev);
diff --git a/drivers/gpu/drm/i915/i915_gem_dmabuf.c b/drivers/gpu/drm/i915/i915_gem_dmabuf.c
index 3e276eee0450..11898cd97596 100644
--- a/drivers/gpu/drm/i915/i915_gem_dmabuf.c
+++ b/drivers/gpu/drm/i915/i915_gem_dmabuf.c
@@ -141,7 +141,7 @@ static int i915_gem_dmabuf_mmap(struct dma_buf *dma_buf, struct vm_area_struct *
if (!obj->base.filp)
return -ENODEV;
- ret = obj->base.filp->f_op->mmap(obj->base.filp, vma);
+ ret = call_mmap(obj->base.filp, vma);
if (ret)
return ret;
diff --git a/drivers/gpu/drm/i915/i915_gem_object.h b/drivers/gpu/drm/i915/i915_gem_object.h
index e89bfdb42102..d26155e0a026 100644
--- a/drivers/gpu/drm/i915/i915_gem_object.h
+++ b/drivers/gpu/drm/i915/i915_gem_object.h
@@ -276,7 +276,7 @@ static inline void i915_gem_object_unlock(struct drm_i915_gem_object *obj)
static inline bool
i915_gem_object_is_dead(const struct drm_i915_gem_object *obj)
{
- return atomic_read(&obj->base.refcount.refcount) == 0;
+ return kref_read(&obj->base.refcount) == 0;
}
static inline bool
diff --git a/drivers/gpu/drm/i915/i915_gem_render_state.c b/drivers/gpu/drm/i915/i915_gem_render_state.c
index b42c81b42487..7032c542a9b1 100644
--- a/drivers/gpu/drm/i915/i915_gem_render_state.c
+++ b/drivers/gpu/drm/i915/i915_gem_render_state.c
@@ -60,7 +60,7 @@ render_state_get_rodata(const struct intel_engine_cs *engine)
* this is sufficient as the null state generator makes the final batch
* with two passes to build command and state separately. At this point
* the size of both are known and it compacts them by relocating the state
- * right after the commands taking care of aligment so we should sufficient
+ * right after the commands taking care of alignment so we should sufficient
* space below them for adding new commands.
*/
#define OUT_BATCH(batch, i, val) \
diff --git a/drivers/gpu/drm/i915/i915_gem_request.c b/drivers/gpu/drm/i915/i915_gem_request.c
index b36a7644e055..1e1d9f2072cd 100644
--- a/drivers/gpu/drm/i915/i915_gem_request.c
+++ b/drivers/gpu/drm/i915/i915_gem_request.c
@@ -24,6 +24,9 @@
#include <linux/prefetch.h>
#include <linux/dma-fence-array.h>
+#include <linux/sched.h>
+#include <linux/sched/clock.h>
+#include <linux/sched/signal.h>
#include "i915_drv.h"
diff --git a/drivers/gpu/drm/i915/i915_gem_userptr.c b/drivers/gpu/drm/i915/i915_gem_userptr.c
index 6a8fa085b74e..22b46398831e 100644
--- a/drivers/gpu/drm/i915/i915_gem_userptr.c
+++ b/drivers/gpu/drm/i915/i915_gem_userptr.c
@@ -31,6 +31,7 @@
#include <linux/mmu_notifier.h>
#include <linux/mempolicy.h>
#include <linux/swap.h>
+#include <linux/sched/mm.h>
struct i915_mm_struct {
struct mm_struct *mm;
@@ -334,7 +335,7 @@ i915_gem_userptr_init__mm_struct(struct drm_i915_gem_object *obj)
mm->i915 = to_i915(obj->base.dev);
mm->mm = current->mm;
- atomic_inc(&current->mm->mm_count);
+ mmgrab(current->mm);
mm->mn = NULL;
@@ -507,7 +508,7 @@ __i915_gem_userptr_get_pages_worker(struct work_struct *_work)
flags |= FOLL_WRITE;
ret = -EFAULT;
- if (atomic_inc_not_zero(&mm->mm_users)) {
+ if (mmget_not_zero(mm)) {
down_read(&mm->mmap_sem);
while (pinned < npages) {
ret = get_user_pages_remote
diff --git a/drivers/gpu/drm/i915/i915_irq.c b/drivers/gpu/drm/i915/i915_irq.c
index 29b002dacbd5..df95733cf112 100644
--- a/drivers/gpu/drm/i915/i915_irq.c
+++ b/drivers/gpu/drm/i915/i915_irq.c
@@ -1960,6 +1960,10 @@ static irqreturn_t valleyview_irq_handler(int irq, void *arg)
* signalled in iir */
valleyview_pipestat_irq_ack(dev_priv, iir, pipe_stats);
+ if (iir & (I915_LPE_PIPE_A_INTERRUPT |
+ I915_LPE_PIPE_B_INTERRUPT))
+ intel_lpe_audio_irq_handler(dev_priv);
+
/*
* VLV_IIR is single buffered, and reflects the level
* from PIPESTAT/PORT_HOTPLUG_STAT, hence clear it last.
@@ -2040,6 +2044,11 @@ static irqreturn_t cherryview_irq_handler(int irq, void *arg)
* signalled in iir */
valleyview_pipestat_irq_ack(dev_priv, iir, pipe_stats);
+ if (iir & (I915_LPE_PIPE_A_INTERRUPT |
+ I915_LPE_PIPE_B_INTERRUPT |
+ I915_LPE_PIPE_C_INTERRUPT))
+ intel_lpe_audio_irq_handler(dev_priv);
+
/*
* VLV_IIR is single buffered, and reflects the level
* from PIPESTAT/PORT_HOTPLUG_STAT, hence clear it last.
@@ -2982,6 +2991,7 @@ static void vlv_display_irq_postinstall(struct drm_i915_private *dev_priv)
u32 pipestat_mask;
u32 enable_mask;
enum pipe pipe;
+ u32 val;
pipestat_mask = PLANE_FLIP_DONE_INT_STATUS_VLV |
PIPE_CRC_DONE_INTERRUPT_STATUS;
@@ -2998,6 +3008,12 @@ static void vlv_display_irq_postinstall(struct drm_i915_private *dev_priv)
WARN_ON(dev_priv->irq_mask != ~0);
+ val = (I915_LPE_PIPE_A_INTERRUPT |
+ I915_LPE_PIPE_B_INTERRUPT |
+ I915_LPE_PIPE_C_INTERRUPT);
+
+ enable_mask |= val;
+
dev_priv->irq_mask = ~enable_mask;
GEN5_IRQ_INIT(VLV_, dev_priv->irq_mask, enable_mask);
@@ -4288,7 +4304,6 @@ void intel_irq_init(struct drm_i915_private *dev_priv)
if (IS_GEN2(dev_priv)) {
/* Gen2 doesn't have a hardware frame counter */
dev->max_vblank_count = 0;
- dev->driver->get_vblank_counter = drm_vblank_no_hw_counter;
} else if (IS_G4X(dev_priv) || INTEL_INFO(dev_priv)->gen >= 5) {
dev->max_vblank_count = 0xffffffff; /* full 32 bit counter */
dev->driver->get_vblank_counter = g4x_get_vblank_counter;
diff --git a/drivers/gpu/drm/i915/i915_reg.h b/drivers/gpu/drm/i915/i915_reg.h
index 243050ea4938..cc843f96576f 100644
--- a/drivers/gpu/drm/i915/i915_reg.h
+++ b/drivers/gpu/drm/i915/i915_reg.h
@@ -2434,6 +2434,22 @@ enum skl_disp_power_wells {
#define I915_ASLE_INTERRUPT (1<<0)
#define I915_BSD_USER_INTERRUPT (1<<25)
+#define I915_HDMI_LPE_AUDIO_BASE (VLV_DISPLAY_BASE + 0x65000)
+#define I915_HDMI_LPE_AUDIO_SIZE 0x1000
+
+/* DisplayPort Audio w/ LPE */
+#define VLV_AUD_CHICKEN_BIT_REG _MMIO(VLV_DISPLAY_BASE + 0x62F38)
+#define VLV_CHICKEN_BIT_DBG_ENABLE (1 << 0)
+
+#define _VLV_AUD_PORT_EN_B_DBG (VLV_DISPLAY_BASE + 0x62F20)
+#define _VLV_AUD_PORT_EN_C_DBG (VLV_DISPLAY_BASE + 0x62F30)
+#define _VLV_AUD_PORT_EN_D_DBG (VLV_DISPLAY_BASE + 0x62F34)
+#define VLV_AUD_PORT_EN_DBG(port) _MMIO_PORT3((port) - PORT_B, \
+ _VLV_AUD_PORT_EN_B_DBG, \
+ _VLV_AUD_PORT_EN_C_DBG, \
+ _VLV_AUD_PORT_EN_D_DBG)
+#define VLV_AMP_MUTE (1 << 1)
+
#define GEN6_BSD_RNCID _MMIO(0x12198)
#define GEN7_FF_THREAD_MODE _MMIO(0x20a0)
diff --git a/drivers/gpu/drm/i915/i915_sw_fence.c b/drivers/gpu/drm/i915/i915_sw_fence.c
index 40f4e5efaf83..a277f8eb7beb 100644
--- a/drivers/gpu/drm/i915/i915_sw_fence.c
+++ b/drivers/gpu/drm/i915/i915_sw_fence.c
@@ -395,10 +395,10 @@ static void timer_i915_sw_fence_wake(unsigned long data)
{
struct i915_sw_dma_fence_cb *cb = (struct i915_sw_dma_fence_cb *)data;
- printk(KERN_WARNING "asynchronous wait on fence %s:%s:%x timed out\n",
- cb->dma->ops->get_driver_name(cb->dma),
- cb->dma->ops->get_timeline_name(cb->dma),
- cb->dma->seqno);
+ pr_warn("asynchronous wait on fence %s:%s:%x timed out\n",
+ cb->dma->ops->get_driver_name(cb->dma),
+ cb->dma->ops->get_timeline_name(cb->dma),
+ cb->dma->seqno);
dma_fence_put(cb->dma);
cb->dma = NULL;
diff --git a/drivers/gpu/drm/i915/intel_audio.c b/drivers/gpu/drm/i915/intel_audio.c
index 1ab401faed34..52c207e81f41 100644
--- a/drivers/gpu/drm/i915/intel_audio.c
+++ b/drivers/gpu/drm/i915/intel_audio.c
@@ -24,6 +24,7 @@
#include <linux/kernel.h>
#include <linux/component.h>
#include <drm/i915_component.h>
+#include <drm/intel_lpe_audio.h>
#include "intel_drv.h"
#include <drm/drmP.h>
@@ -623,13 +624,28 @@ void intel_audio_codec_enable(struct intel_encoder *intel_encoder,
dev_priv->av_enc_map[pipe] = intel_encoder;
mutex_unlock(&dev_priv->av_mutex);
- /* audio drivers expect pipe = -1 to indicate Non-MST cases */
- if (intel_encoder->type != INTEL_OUTPUT_DP_MST)
- pipe = -1;
-
- if (acomp && acomp->audio_ops && acomp->audio_ops->pin_eld_notify)
+ if (acomp && acomp->audio_ops && acomp->audio_ops->pin_eld_notify) {
+ /* audio drivers expect pipe = -1 to indicate Non-MST cases */
+ if (intel_encoder->type != INTEL_OUTPUT_DP_MST)
+ pipe = -1;
acomp->audio_ops->pin_eld_notify(acomp->audio_ops->audio_ptr,
(int) port, (int) pipe);
+ }
+
+ switch (intel_encoder->type) {
+ case INTEL_OUTPUT_HDMI:
+ intel_lpe_audio_notify(dev_priv, connector->eld, port, pipe,
+ crtc_state->port_clock,
+ false, 0);
+ break;
+ case INTEL_OUTPUT_DP:
+ intel_lpe_audio_notify(dev_priv, connector->eld, port, pipe,
+ adjusted_mode->crtc_clock,
+ true, crtc_state->port_clock);
+ break;
+ default:
+ break;
+ }
}
/**
@@ -656,13 +672,15 @@ void intel_audio_codec_disable(struct intel_encoder *intel_encoder)
dev_priv->av_enc_map[pipe] = NULL;
mutex_unlock(&dev_priv->av_mutex);
- /* audio drivers expect pipe = -1 to indicate Non-MST cases */
- if (intel_encoder->type != INTEL_OUTPUT_DP_MST)
- pipe = -1;
-
- if (acomp && acomp->audio_ops && acomp->audio_ops->pin_eld_notify)
+ if (acomp && acomp->audio_ops && acomp->audio_ops->pin_eld_notify) {
+ /* audio drivers expect pipe = -1 to indicate Non-MST cases */
+ if (intel_encoder->type != INTEL_OUTPUT_DP_MST)
+ pipe = -1;
acomp->audio_ops->pin_eld_notify(acomp->audio_ops->audio_ptr,
(int) port, (int) pipe);
+ }
+
+ intel_lpe_audio_notify(dev_priv, NULL, port, pipe, 0, false, 0);
}
/**
@@ -956,3 +974,28 @@ void i915_audio_component_cleanup(struct drm_i915_private *dev_priv)
component_del(dev_priv->drm.dev, &i915_audio_component_bind_ops);
dev_priv->audio_component_registered = false;
}
+
+/**
+ * intel_audio_init() - Initialize the audio driver either using
+ * component framework or using lpe audio bridge
+ * @dev_priv: the i915 drm device private data
+ *
+ */
+void intel_audio_init(struct drm_i915_private *dev_priv)
+{
+ if (intel_lpe_audio_init(dev_priv) < 0)
+ i915_audio_component_init(dev_priv);
+}
+
+/**
+ * intel_audio_deinit() - deinitialize the audio driver
+ * @dev_priv: the i915 drm device private data
+ *
+ */
+void intel_audio_deinit(struct drm_i915_private *dev_priv)
+{
+ if ((dev_priv)->lpe_audio.platdev != NULL)
+ intel_lpe_audio_teardown(dev_priv);
+ else
+ i915_audio_component_cleanup(dev_priv);
+}
diff --git a/drivers/gpu/drm/i915/intel_breadcrumbs.c b/drivers/gpu/drm/i915/intel_breadcrumbs.c
index f96d0f368f59..2a1ed6d7ad4d 100644
--- a/drivers/gpu/drm/i915/intel_breadcrumbs.c
+++ b/drivers/gpu/drm/i915/intel_breadcrumbs.c
@@ -23,6 +23,7 @@
*/
#include <linux/kthread.h>
+#include <uapi/linux/sched/types.h>
#include "i915_drv.h"
diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c
index e44160f35afd..e77ca7dfa44d 100644
--- a/drivers/gpu/drm/i915/intel_display.c
+++ b/drivers/gpu/drm/i915/intel_display.c
@@ -3461,7 +3461,8 @@ static void intel_update_primary_planes(struct drm_device *dev)
static int
__intel_display_resume(struct drm_device *dev,
- struct drm_atomic_state *state)
+ struct drm_atomic_state *state,
+ struct drm_modeset_acquire_ctx *ctx)
{
struct drm_crtc_state *crtc_state;
struct drm_crtc *crtc;
@@ -3486,7 +3487,7 @@ __intel_display_resume(struct drm_device *dev,
if (!HAS_GMCH_DISPLAY(to_i915(dev)))
to_intel_atomic_state(state)->skip_intermediate_wm = true;
- ret = drm_atomic_commit(state);
+ ret = drm_atomic_helper_commit_duplicated_state(state, ctx);
WARN_ON(ret == -EDEADLK);
return ret;
@@ -3576,7 +3577,7 @@ void intel_finish_reset(struct drm_i915_private *dev_priv)
*/
intel_update_primary_planes(dev);
} else {
- ret = __intel_display_resume(dev, state);
+ ret = __intel_display_resume(dev, state, ctx);
if (ret)
DRM_ERROR("Restoring old state failed with %i\n", ret);
}
@@ -3596,7 +3597,7 @@ void intel_finish_reset(struct drm_i915_private *dev_priv)
dev_priv->display.hpd_irq_setup(dev_priv);
spin_unlock_irq(&dev_priv->irq_lock);
- ret = __intel_display_resume(dev, state);
+ ret = __intel_display_resume(dev, state, ctx);
if (ret)
DRM_ERROR("Restoring old state failed with %i\n", ret);
@@ -9689,7 +9690,7 @@ void intel_release_load_detect_pipe(struct drm_connector *connector,
if (!state)
return;
- ret = drm_atomic_commit(state);
+ ret = drm_atomic_helper_commit_duplicated_state(state, ctx);
if (ret)
DRM_DEBUG_KMS("Couldn't release load detect pipe: %i\n", ret);
drm_atomic_state_put(state);
@@ -15577,7 +15578,7 @@ void intel_display_resume(struct drm_device *dev)
}
if (!ret)
- ret = __intel_display_resume(dev, state);
+ ret = __intel_display_resume(dev, state, &ctx);
drm_modeset_drop_locks(&ctx);
drm_modeset_acquire_fini(&ctx);
diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h
index 3c8b4522ae66..3af20c1f2ba8 100644
--- a/drivers/gpu/drm/i915/intel_drv.h
+++ b/drivers/gpu/drm/i915/intel_drv.h
@@ -28,6 +28,7 @@
#include <linux/async.h>
#include <linux/i2c.h>
#include <linux/hdmi.h>
+#include <linux/sched/clock.h>
#include <drm/i915_drm.h>
#include "i915_drv.h"
#include <drm/drm_crtc.h>
@@ -1264,6 +1265,8 @@ 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);
+void intel_audio_init(struct drm_i915_private *dev_priv);
+void intel_audio_deinit(struct drm_i915_private *dev_priv);
/* intel_cdclk.c */
void skl_init_cdclk(struct drm_i915_private *dev_priv);
@@ -1932,7 +1935,6 @@ void lspcon_wait_pcon_mode(struct intel_lspcon *lspcon);
/* intel_pipe_crc.c */
int intel_pipe_crc_create(struct drm_minor *minor);
-void intel_pipe_crc_cleanup(struct drm_minor *minor);
#ifdef CONFIG_DEBUG_FS
int intel_crtc_set_crc_source(struct drm_crtc *crtc, const char *source_name,
size_t *values_cnt);
diff --git a/drivers/gpu/drm/i915/intel_fbdev.c b/drivers/gpu/drm/i915/intel_fbdev.c
index 82993a87654c..f7e9a4e69595 100644
--- a/drivers/gpu/drm/i915/intel_fbdev.c
+++ b/drivers/gpu/drm/i915/intel_fbdev.c
@@ -246,7 +246,7 @@ static int intelfb_create(struct drm_fb_helper *helper,
if (IS_ERR(vaddr)) {
DRM_ERROR("Failed to remap framebuffer into virtual memory\n");
ret = PTR_ERR(vaddr);
- goto out_destroy_fbi;
+ goto out_unpin;
}
info->screen_base = vaddr;
info->screen_size = vma->node.size;
@@ -274,8 +274,6 @@ static int intelfb_create(struct drm_fb_helper *helper,
vga_switcheroo_client_fb_set(pdev, info);
return 0;
-out_destroy_fbi:
- drm_fb_helper_release_fbi(helper);
out_unpin:
intel_unpin_fb_vma(vma);
out_unlock:
@@ -534,7 +532,6 @@ static void intel_fbdev_destroy(struct intel_fbdev *ifbdev)
*/
drm_fb_helper_unregister_fbi(&ifbdev->helper);
- drm_fb_helper_release_fbi(&ifbdev->helper);
drm_fb_helper_fini(&ifbdev->helper);
diff --git a/drivers/gpu/drm/i915/intel_hdmi.c b/drivers/gpu/drm/i915/intel_hdmi.c
index 048f76d329bb..c2184f755ec6 100644
--- a/drivers/gpu/drm/i915/intel_hdmi.c
+++ b/drivers/gpu/drm/i915/intel_hdmi.c
@@ -36,6 +36,7 @@
#include <drm/drm_edid.h>
#include "intel_drv.h"
#include <drm/i915_drm.h>
+#include <drm/intel_lpe_audio.h>
#include "i915_drv.h"
static struct drm_device *intel_hdmi_to_dev(struct intel_hdmi *intel_hdmi)
diff --git a/drivers/gpu/drm/i915/intel_lpe_audio.c b/drivers/gpu/drm/i915/intel_lpe_audio.c
new file mode 100644
index 000000000000..7a5b41b1c024
--- /dev/null
+++ b/drivers/gpu/drm/i915/intel_lpe_audio.c
@@ -0,0 +1,392 @@
+/*
+ * Copyright © 2016 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.
+ *
+ * Authors:
+ * Pierre-Louis Bossart <pierre-louis.bossart@linux.intel.com>
+ * Jerome Anand <jerome.anand@intel.com>
+ * based on VED patches
+ *
+ */
+
+/**
+ * DOC: LPE Audio integration for HDMI or DP playback
+ *
+ * Motivation:
+ * Atom platforms (e.g. valleyview and cherryTrail) integrates a DMA-based
+ * interface as an alternative to the traditional HDaudio path. While this
+ * mode is unrelated to the LPE aka SST audio engine, the documentation refers
+ * to this mode as LPE so we keep this notation for the sake of consistency.
+ *
+ * The interface is handled by a separate standalone driver maintained in the
+ * ALSA subsystem for simplicity. To minimize the interaction between the two
+ * subsystems, a bridge is setup between the hdmi-lpe-audio and i915:
+ * 1. Create a platform device to share MMIO/IRQ resources
+ * 2. Make the platform device child of i915 device for runtime PM.
+ * 3. Create IRQ chip to forward the LPE audio irqs.
+ * the hdmi-lpe-audio driver probes the lpe audio device and creates a new
+ * sound card
+ *
+ * Threats:
+ * Due to the restriction in Linux platform device model, user need manually
+ * uninstall the hdmi-lpe-audio driver before uninstalling i915 module,
+ * otherwise we might run into use-after-free issues after i915 removes the
+ * platform device: even though hdmi-lpe-audio driver is released, the modules
+ * is still in "installed" status.
+ *
+ * Implementation:
+ * The MMIO/REG platform resources are created according to the registers
+ * specification.
+ * When forwarding LPE audio irqs, the flow control handler selection depends
+ * on the platform, for example on valleyview handle_simple_irq is enough.
+ *
+ */
+
+#include <linux/acpi.h>
+#include <linux/device.h>
+#include <linux/pci.h>
+
+#include "i915_drv.h"
+#include <linux/delay.h>
+#include <drm/intel_lpe_audio.h>
+
+#define HAS_LPE_AUDIO(dev_priv) ((dev_priv)->lpe_audio.platdev != NULL)
+
+static struct platform_device *
+lpe_audio_platdev_create(struct drm_i915_private *dev_priv)
+{
+ int ret;
+ struct drm_device *dev = &dev_priv->drm;
+ struct platform_device_info pinfo = {};
+ struct resource *rsc;
+ struct platform_device *platdev;
+ struct intel_hdmi_lpe_audio_pdata *pdata;
+
+ pdata = kzalloc(sizeof(*pdata), GFP_KERNEL);
+ if (!pdata)
+ return ERR_PTR(-ENOMEM);
+
+ rsc = kcalloc(2, sizeof(*rsc), GFP_KERNEL);
+ if (!rsc) {
+ kfree(pdata);
+ return ERR_PTR(-ENOMEM);
+ }
+
+ rsc[0].start = rsc[0].end = dev_priv->lpe_audio.irq;
+ rsc[0].flags = IORESOURCE_IRQ;
+ rsc[0].name = "hdmi-lpe-audio-irq";
+
+ rsc[1].start = pci_resource_start(dev->pdev, 0) +
+ I915_HDMI_LPE_AUDIO_BASE;
+ rsc[1].end = pci_resource_start(dev->pdev, 0) +
+ I915_HDMI_LPE_AUDIO_BASE + I915_HDMI_LPE_AUDIO_SIZE - 1;
+ rsc[1].flags = IORESOURCE_MEM;
+ rsc[1].name = "hdmi-lpe-audio-mmio";
+
+ pinfo.parent = dev->dev;
+ pinfo.name = "hdmi-lpe-audio";
+ pinfo.id = -1;
+ pinfo.res = rsc;
+ pinfo.num_res = 2;
+ pinfo.data = pdata;
+ pinfo.size_data = sizeof(*pdata);
+ pinfo.dma_mask = DMA_BIT_MASK(32);
+
+ spin_lock_init(&pdata->lpe_audio_slock);
+
+ platdev = platform_device_register_full(&pinfo);
+ if (IS_ERR(platdev)) {
+ ret = PTR_ERR(platdev);
+ DRM_ERROR("Failed to allocate LPE audio platform device\n");
+ goto err;
+ }
+
+ kfree(rsc);
+
+ return platdev;
+
+err:
+ kfree(rsc);
+ kfree(pdata);
+ return ERR_PTR(ret);
+}
+
+static void lpe_audio_platdev_destroy(struct drm_i915_private *dev_priv)
+{
+ platform_device_unregister(dev_priv->lpe_audio.platdev);
+ kfree(dev_priv->lpe_audio.platdev->dev.dma_mask);
+}
+
+static void lpe_audio_irq_unmask(struct irq_data *d)
+{
+ struct drm_i915_private *dev_priv = d->chip_data;
+ unsigned long irqflags;
+ u32 val = (I915_LPE_PIPE_A_INTERRUPT |
+ I915_LPE_PIPE_B_INTERRUPT);
+
+ if (IS_CHERRYVIEW(dev_priv))
+ val |= I915_LPE_PIPE_C_INTERRUPT;
+
+ spin_lock_irqsave(&dev_priv->irq_lock, irqflags);
+
+ dev_priv->irq_mask &= ~val;
+ I915_WRITE(VLV_IIR, val);
+ I915_WRITE(VLV_IIR, val);
+ I915_WRITE(VLV_IMR, dev_priv->irq_mask);
+ POSTING_READ(VLV_IMR);
+
+ spin_unlock_irqrestore(&dev_priv->irq_lock, irqflags);
+}
+
+static void lpe_audio_irq_mask(struct irq_data *d)
+{
+ struct drm_i915_private *dev_priv = d->chip_data;
+ unsigned long irqflags;
+ u32 val = (I915_LPE_PIPE_A_INTERRUPT |
+ I915_LPE_PIPE_B_INTERRUPT);
+
+ if (IS_CHERRYVIEW(dev_priv))
+ val |= I915_LPE_PIPE_C_INTERRUPT;
+
+ spin_lock_irqsave(&dev_priv->irq_lock, irqflags);
+
+ dev_priv->irq_mask |= val;
+ I915_WRITE(VLV_IMR, dev_priv->irq_mask);
+ I915_WRITE(VLV_IIR, val);
+ I915_WRITE(VLV_IIR, val);
+ POSTING_READ(VLV_IIR);
+
+ spin_unlock_irqrestore(&dev_priv->irq_lock, irqflags);
+}
+
+static struct irq_chip lpe_audio_irqchip = {
+ .name = "hdmi_lpe_audio_irqchip",
+ .irq_mask = lpe_audio_irq_mask,
+ .irq_unmask = lpe_audio_irq_unmask,
+};
+
+static int lpe_audio_irq_init(struct drm_i915_private *dev_priv)
+{
+ int irq = dev_priv->lpe_audio.irq;
+
+ WARN_ON(!intel_irqs_enabled(dev_priv));
+ irq_set_chip_and_handler_name(irq,
+ &lpe_audio_irqchip,
+ handle_simple_irq,
+ "hdmi_lpe_audio_irq_handler");
+
+ return irq_set_chip_data(irq, dev_priv);
+}
+
+static bool lpe_audio_detect(struct drm_i915_private *dev_priv)
+{
+ int lpe_present = false;
+
+ if (IS_VALLEYVIEW(dev_priv) || IS_CHERRYVIEW(dev_priv)) {
+ static const struct pci_device_id atom_hdaudio_ids[] = {
+ /* Baytrail */
+ {PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0x0f04)},
+ /* Braswell */
+ {PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0x2284)},
+ {}
+ };
+
+ if (!pci_dev_present(atom_hdaudio_ids)) {
+ DRM_INFO("%s\n", "HDaudio controller not detected, using LPE audio instead\n");
+ lpe_present = true;
+ }
+ }
+ return lpe_present;
+}
+
+static int lpe_audio_setup(struct drm_i915_private *dev_priv)
+{
+ int ret;
+
+ dev_priv->lpe_audio.irq = irq_alloc_desc(0);
+ if (dev_priv->lpe_audio.irq < 0) {
+ DRM_ERROR("Failed to allocate IRQ desc: %d\n",
+ dev_priv->lpe_audio.irq);
+ ret = dev_priv->lpe_audio.irq;
+ goto err;
+ }
+
+ DRM_DEBUG("irq = %d\n", dev_priv->lpe_audio.irq);
+
+ ret = lpe_audio_irq_init(dev_priv);
+
+ if (ret) {
+ DRM_ERROR("Failed to initialize irqchip for lpe audio: %d\n",
+ ret);
+ goto err_free_irq;
+ }
+
+ dev_priv->lpe_audio.platdev = lpe_audio_platdev_create(dev_priv);
+
+ if (IS_ERR(dev_priv->lpe_audio.platdev)) {
+ ret = PTR_ERR(dev_priv->lpe_audio.platdev);
+ DRM_ERROR("Failed to create lpe audio platform device: %d\n",
+ ret);
+ goto err_free_irq;
+ }
+
+ /* enable chicken bit; at least this is required for Dell Wyse 3040
+ * with DP outputs (but only sometimes by some reason!)
+ */
+ I915_WRITE(VLV_AUD_CHICKEN_BIT_REG, VLV_CHICKEN_BIT_DBG_ENABLE);
+
+ return 0;
+err_free_irq:
+ irq_free_desc(dev_priv->lpe_audio.irq);
+err:
+ dev_priv->lpe_audio.irq = -1;
+ dev_priv->lpe_audio.platdev = NULL;
+ return ret;
+}
+
+/**
+ * intel_lpe_audio_irq_handler() - forwards the LPE audio irq
+ * @dev_priv: the i915 drm device private data
+ *
+ * the LPE Audio irq is forwarded to the irq handler registered by LPE audio
+ * driver.
+ */
+void intel_lpe_audio_irq_handler(struct drm_i915_private *dev_priv)
+{
+ int ret;
+
+ if (!HAS_LPE_AUDIO(dev_priv))
+ return;
+
+ ret = generic_handle_irq(dev_priv->lpe_audio.irq);
+ if (ret)
+ DRM_ERROR_RATELIMITED("error handling LPE audio irq: %d\n",
+ ret);
+}
+
+/**
+ * intel_lpe_audio_init() - detect and setup the bridge between HDMI LPE Audio
+ * driver and i915
+ * @dev_priv: the i915 drm device private data
+ *
+ * Return: 0 if successful. non-zero if detection or
+ * llocation/initialization fails
+ */
+int intel_lpe_audio_init(struct drm_i915_private *dev_priv)
+{
+ int ret = -ENODEV;
+
+ if (lpe_audio_detect(dev_priv)) {
+ ret = lpe_audio_setup(dev_priv);
+ if (ret < 0)
+ DRM_ERROR("failed to setup LPE Audio bridge\n");
+ }
+ return ret;
+}
+
+/**
+ * intel_lpe_audio_teardown() - destroy the bridge between HDMI LPE
+ * audio driver and i915
+ * @dev_priv: the i915 drm device private data
+ *
+ * release all the resources for LPE audio <-> i915 bridge.
+ */
+void intel_lpe_audio_teardown(struct drm_i915_private *dev_priv)
+{
+ struct irq_desc *desc;
+
+ if (!HAS_LPE_AUDIO(dev_priv))
+ return;
+
+ desc = irq_to_desc(dev_priv->lpe_audio.irq);
+
+ lpe_audio_irq_mask(&desc->irq_data);
+
+ lpe_audio_platdev_destroy(dev_priv);
+
+ irq_free_desc(dev_priv->lpe_audio.irq);
+}
+
+
+/**
+ * intel_lpe_audio_notify() - notify lpe audio event
+ * audio driver and i915
+ * @dev_priv: the i915 drm device private data
+ * @eld : ELD data
+ * @port: port id
+ * @tmds_clk_speed: tmds clock frequency in Hz
+ *
+ * Notify lpe audio driver of eld change.
+ */
+void intel_lpe_audio_notify(struct drm_i915_private *dev_priv,
+ void *eld, int port, int pipe, int tmds_clk_speed,
+ bool dp_output, int link_rate)
+{
+ unsigned long irq_flags;
+ struct intel_hdmi_lpe_audio_pdata *pdata = NULL;
+ u32 audio_enable;
+
+ if (!HAS_LPE_AUDIO(dev_priv))
+ return;
+
+ pdata = dev_get_platdata(
+ &(dev_priv->lpe_audio.platdev->dev));
+
+ spin_lock_irqsave(&pdata->lpe_audio_slock, irq_flags);
+
+ audio_enable = I915_READ(VLV_AUD_PORT_EN_DBG(port));
+
+ if (eld != NULL) {
+ memcpy(pdata->eld.eld_data, eld,
+ HDMI_MAX_ELD_BYTES);
+ pdata->eld.port_id = port;
+ pdata->eld.pipe_id = pipe;
+ pdata->hdmi_connected = true;
+
+ pdata->dp_output = dp_output;
+ if (tmds_clk_speed)
+ pdata->tmds_clock_speed = tmds_clk_speed;
+ if (link_rate)
+ pdata->link_rate = link_rate;
+
+ /* Unmute the amp for both DP and HDMI */
+ I915_WRITE(VLV_AUD_PORT_EN_DBG(port),
+ audio_enable & ~VLV_AMP_MUTE);
+
+ } else {
+ memset(pdata->eld.eld_data, 0,
+ HDMI_MAX_ELD_BYTES);
+ pdata->hdmi_connected = false;
+ pdata->dp_output = false;
+
+ /* Mute the amp for both DP and HDMI */
+ I915_WRITE(VLV_AUD_PORT_EN_DBG(port),
+ audio_enable | VLV_AMP_MUTE);
+ }
+
+ if (pdata->notify_audio_lpe)
+ pdata->notify_audio_lpe(dev_priv->lpe_audio.platdev);
+ else
+ pdata->notify_pending = true;
+
+ spin_unlock_irqrestore(&pdata->lpe_audio_slock,
+ irq_flags);
+}
diff --git a/drivers/gpu/drm/i915/intel_pipe_crc.c b/drivers/gpu/drm/i915/intel_pipe_crc.c
index c782b7878288..9fd9c70baeed 100644
--- a/drivers/gpu/drm/i915/intel_pipe_crc.c
+++ b/drivers/gpu/drm/i915/intel_pipe_crc.c
@@ -36,31 +36,6 @@ struct pipe_crc_info {
enum pipe pipe;
};
-/* As the drm_debugfs_init() routines are called before dev->dev_private is
- * allocated we need to hook into the minor for release.
- */
-static int drm_add_fake_info_node(struct drm_minor *minor,
- struct dentry *ent, const void *key)
-{
- struct drm_info_node *node;
-
- node = kmalloc(sizeof(*node), GFP_KERNEL);
- if (node == NULL) {
- debugfs_remove(ent);
- return -ENOMEM;
- }
-
- node->minor = minor;
- node->dent = ent;
- node->info_ent = (void *) key;
-
- mutex_lock(&minor->debugfs_lock);
- list_add(&node->list, &minor->debugfs_list);
- mutex_unlock(&minor->debugfs_lock);
-
- return 0;
-}
-
static int i915_pipe_crc_open(struct inode *inode, struct file *filep)
{
struct pipe_crc_info *info = inode->i_private;
@@ -209,22 +184,6 @@ static struct pipe_crc_info i915_pipe_crc_data[I915_MAX_PIPES] = {
},
};
-static int i915_pipe_crc_create(struct dentry *root, struct drm_minor *minor,
- enum pipe pipe)
-{
- struct drm_i915_private *dev_priv = to_i915(minor->dev);
- struct dentry *ent;
- struct pipe_crc_info *info = &i915_pipe_crc_data[pipe];
-
- info->dev_priv = dev_priv;
- ent = debugfs_create_file(info->name, S_IRUGO, root, info,
- &i915_pipe_crc_fops);
- if (!ent)
- return -ENOMEM;
-
- return drm_add_fake_info_node(minor, ent, info);
-}
-
static const char * const pipe_crc_sources[] = {
"none",
"plane1",
@@ -928,27 +887,22 @@ void intel_display_crc_init(struct drm_i915_private *dev_priv)
int intel_pipe_crc_create(struct drm_minor *minor)
{
- int ret, i;
-
- for (i = 0; i < ARRAY_SIZE(i915_pipe_crc_data); i++) {
- ret = i915_pipe_crc_create(minor->debugfs_root, minor, i);
- if (ret)
- return ret;
- }
-
- return 0;
-}
-
-void intel_pipe_crc_cleanup(struct drm_minor *minor)
-{
+ struct drm_i915_private *dev_priv = to_i915(minor->dev);
+ struct dentry *ent;
int i;
for (i = 0; i < ARRAY_SIZE(i915_pipe_crc_data); i++) {
- struct drm_info_list *info_list =
- (struct drm_info_list *)&i915_pipe_crc_data[i];
+ struct pipe_crc_info *info = &i915_pipe_crc_data[i];
- drm_debugfs_remove_files(info_list, 1, minor);
+ info->dev_priv = dev_priv;
+ ent = debugfs_create_file(info->name, S_IRUGO,
+ minor->debugfs_root, info,
+ &i915_pipe_crc_fops);
+ if (!ent)
+ return -ENOMEM;
}
+
+ return 0;
}
int intel_crtc_set_crc_source(struct drm_crtc *crtc, const char *source_name,