>From 66d9a3fd80f1dc0471949680a076c7696a869adc Mon Sep 17 00:00:00 2001
From: David Henningsson <david.henningsson@canonical.com>
Date: Thu, 2 May 2013 16:38:54 +0200
Subject: [PATCH] ALSA: hda - implement i915 power well callbacks

Draft patch

Signed-off-by: David Henningsson <david.henningsson@canonical.com>
---
 sound/pci/hda/Kconfig           |   14 ++++++++++
 sound/pci/hda/Makefile          |    4 +++
 sound/pci/hda/patch_hdmi.c      |   19 ++++++++++---
 sound/pci/hda/patch_hdmi.h      |    6 ++++
 sound/pci/hda/patch_hdmi_i915.c |   58 +++++++++++++++++++++++++++++++++++++++
 5 files changed, 97 insertions(+), 4 deletions(-)
 create mode 100644 sound/pci/hda/patch_hdmi.h
 create mode 100644 sound/pci/hda/patch_hdmi_i915.c

diff --git a/sound/pci/hda/Kconfig b/sound/pci/hda/Kconfig
index 80a7d44..18226de 100644
--- a/sound/pci/hda/Kconfig
+++ b/sound/pci/hda/Kconfig
@@ -152,6 +152,20 @@ config SND_HDA_CODEC_HDMI
 	  snd-hda-codec-hdmi.
 	  This module is automatically loaded at probing.
 
+config SND_HDA_CODEC_HDMI_I915
+	bool "Build HDMI/DisplayPort HD-audio codec support for i915 cards"
+	depends on SND_HDA_CODEC_HDMI
+	depends on DRM_I915
+	default y
+	help
+	  Say Y here to include full HDMI and DisplayPort HD-audio codec
+	  support for Intel graphics cards based on the i915 driver.
+
+	  When the HD-audio driver is built as a module, the codec
+	  support code is also built as another module,
+	  snd-hda-codec-hdmi-i915.
+	  This module is automatically loaded at probing.
+
 config SND_HDA_CODEC_CIRRUS
 	bool "Build Cirrus Logic codec support"
 	default y
diff --git a/sound/pci/hda/Makefile b/sound/pci/hda/Makefile
index 24a2514..ed0b2de 100644
--- a/sound/pci/hda/Makefile
+++ b/sound/pci/hda/Makefile
@@ -21,6 +21,7 @@ snd-hda-codec-ca0132-objs :=	patch_ca0132.o
 snd-hda-codec-conexant-objs :=	patch_conexant.o
 snd-hda-codec-via-objs :=	patch_via.o
 snd-hda-codec-hdmi-objs :=	patch_hdmi.o hda_eld.o
+snd-hda-codec-hdmi-i915-objs :=	patch_hdmi_i915.o
 
 # common driver
 obj-$(CONFIG_SND_HDA_INTEL) := snd-hda-codec.o
@@ -59,6 +60,9 @@ endif
 ifdef CONFIG_SND_HDA_CODEC_HDMI
 obj-$(CONFIG_SND_HDA_INTEL) += snd-hda-codec-hdmi.o
 endif
+ifdef CONFIG_SND_HDA_CODEC_HDMI_I915
+obj-$(CONFIG_SND_HDA_INTEL) += snd-hda-codec-hdmi-i915.o
+endif
 
 # this must be the last entry after codec drivers;
 # otherwise the codec patches won't be hooked before the PCI probe
diff --git a/sound/pci/hda/patch_hdmi.c b/sound/pci/hda/patch_hdmi.c
index 32930e6..4fbbc1e 100644
--- a/sound/pci/hda/patch_hdmi.c
+++ b/sound/pci/hda/patch_hdmi.c
@@ -1892,8 +1892,7 @@ static const struct hda_fixup hdmi_fixups[] = {
 	},
 };
 
-
-static int patch_generic_hdmi(struct hda_codec *codec)
+int initialize_hdmi_patch_ops(struct hda_codec *codec, struct hda_codec_ops *ops)
 {
 	struct hdmi_spec *spec;
 
@@ -1916,12 +1915,26 @@ static int patch_generic_hdmi(struct hda_codec *codec)
 		return -EINVAL;
 	}
 	codec->patch_ops = generic_hdmi_patch_ops;
+#ifdef CONFIG_PM
+	if (ops != NULL) {
+		if (ops->suspend)
+			codec->patch_ops.suspend = ops->suspend;
+		if (ops->resume)
+			codec->patch_ops.resume = ops->resume;
+	}
+#endif
 	generic_hdmi_init_per_pins(codec);
 
 	init_channel_allocations();
 
 	return 0;
 }
+EXPORT_SYMBOL_HDA(initialize_i915_hdmi)
+
+static int patch_generic_hdmi(struct hda_codec *codec)
+{
+	return initialize_hdmi_patch_ops(codec, NULL);
+}
 
 /*
  * Shared non-generic implementations
@@ -2559,7 +2572,6 @@ static const struct hda_codec_preset snd_hda_preset_hdmi[] = {
 { .id = 0x80862804, .name = "IbexPeak HDMI",	.patch = patch_generic_hdmi },
 { .id = 0x80862805, .name = "CougarPoint HDMI",	.patch = patch_generic_hdmi },
 { .id = 0x80862806, .name = "PantherPoint HDMI", .patch = patch_generic_hdmi },
-{ .id = 0x80862807, .name = "Haswell HDMI",	.patch = patch_generic_hdmi },
 { .id = 0x80862880, .name = "CedarTrail HDMI",	.patch = patch_generic_hdmi },
 { .id = 0x808629fb, .name = "Crestline HDMI",	.patch = patch_generic_hdmi },
 {} /* terminator */
@@ -2612,7 +2624,6 @@ MODULE_ALIAS("snd-hda-codec-id:80862803");
 MODULE_ALIAS("snd-hda-codec-id:80862804");
 MODULE_ALIAS("snd-hda-codec-id:80862805");
 MODULE_ALIAS("snd-hda-codec-id:80862806");
-MODULE_ALIAS("snd-hda-codec-id:80862807");
 MODULE_ALIAS("snd-hda-codec-id:80862880");
 MODULE_ALIAS("snd-hda-codec-id:808629fb");
 
diff --git a/sound/pci/hda/patch_hdmi.h b/sound/pci/hda/patch_hdmi.h
new file mode 100644
index 0000000..ab60c8b
--- /dev/null
+++ b/sound/pci/hda/patch_hdmi.h
@@ -0,0 +1,6 @@
+#ifndef __SOUND_HDA_PATCH_HDMI_H
+#define __SOUND_HDA_PATCH_HDMI_H
+
+int initialize_hdmi_patch_ops(struct hda_codec *codec, struct hda_codec_ops *ops);
+
+#endif
diff --git a/sound/pci/hda/patch_hdmi_i915.c b/sound/pci/hda/patch_hdmi_i915.c
new file mode 100644
index 0000000..e82a3eb
--- /dev/null
+++ b/sound/pci/hda/patch_hdmi_i915.c
@@ -0,0 +1,58 @@
+#include <drm/audio_drm.h>
+#include "patch_hdmi.h"
+
+#ifdef CONFIG_PM
+static int i915_suspend(struct hda_codec *codec)
+{
+	release_power_well(); /* Or other preferred name */
+}
+
+static int i915_resume(struct hda_codec *codec)
+{
+	request_power_well(); /* Or other preferred name */
+
+	if (codec->patch_ops.init)
+		codec->patch_ops.init(codec);
+	snd_hda_codec_resume_amp(codec);
+	snd_hda_codec_resume_cache(codec);
+}
+#endif
+
+static const struct hda_codec_ops i915_patch_ops = {
+#ifdef CONFIG_PM
+	.suspend	= i915_suspend,
+	.resume		= i915_resume,
+#endif
+}
+
+
+static int patch_i915_hdmi(struct hda_codec *codec)
+{
+	return initialize_hdmi_ops(codec, i915_patch_ops);
+}
+
+
+static const struct hda_codec_preset snd_hda_preset_hdmi[] = {
+{ .id = 0x80862807, .name = "Haswell HDMI",	.patch = patch_i915_hdmi },
+{} /* terminator */
+};
+
+MODULE_ALIAS("snd-hda-codec-id:80862807");
+
+static struct hda_codec_preset_list intel_list = {
+	.preset = snd_hda_preset_hdmi,
+	.owner = THIS_MODULE,
+};
+
+static int __init patch_hdmi_i915_init(void)
+{
+	return snd_hda_add_codec_preset(&intel_list);
+}
+
+static void __exit patch_hdmi_i915_exit(void)
+{
+	snd_hda_delete_codec_preset(&intel_list);
+}
+
+module_init(patch_hdmi_i915_init)
+module_exit(patch_hdmi_i915_exit)
-- 
1.7.9.5

