summaryrefslogtreecommitdiff
path: root/sound/pci
diff options
context:
space:
mode:
Diffstat (limited to 'sound/pci')
-rw-r--r--sound/pci/hda/hda_codec.c68
-rw-r--r--sound/pci/hda/hda_codec.h2
-rw-r--r--sound/pci/hda/patch_hdmi.c57
3 files changed, 94 insertions, 33 deletions
diff --git a/sound/pci/hda/hda_codec.c b/sound/pci/hda/hda_codec.c
index 20a171ac4bb2..3fd0c16fa602 100644
--- a/sound/pci/hda/hda_codec.c
+++ b/sound/pci/hda/hda_codec.c
@@ -858,6 +858,39 @@ static void snd_hda_codec_dev_release(struct device *dev)
kfree(codec);
}
+#define DEV_NAME_LEN 31
+
+static int snd_hda_codec_device_init(struct hda_bus *bus, struct snd_card *card,
+ unsigned int codec_addr, struct hda_codec **codecp)
+{
+ char name[DEV_NAME_LEN];
+ struct hda_codec *codec;
+ int err;
+
+ dev_dbg(card->dev, "%s: entry\n", __func__);
+
+ if (snd_BUG_ON(!bus))
+ return -EINVAL;
+ if (snd_BUG_ON(codec_addr > HDA_MAX_CODEC_ADDRESS))
+ return -EINVAL;
+
+ codec = kzalloc(sizeof(*codec), GFP_KERNEL);
+ if (!codec)
+ return -ENOMEM;
+
+ sprintf(name, "hdaudioC%dD%d", card->number, codec_addr);
+ err = snd_hdac_device_init(&codec->core, &bus->core, name, codec_addr);
+ if (err < 0) {
+ kfree(codec);
+ return err;
+ }
+
+ codec->core.type = HDA_DEV_LEGACY;
+ *codecp = codec;
+
+ return err;
+}
+
/**
* snd_hda_codec_new - create a HDA codec
* @bus: the bus to assign
@@ -869,7 +902,19 @@ static void snd_hda_codec_dev_release(struct device *dev)
int snd_hda_codec_new(struct hda_bus *bus, struct snd_card *card,
unsigned int codec_addr, struct hda_codec **codecp)
{
- struct hda_codec *codec;
+ int ret;
+
+ ret = snd_hda_codec_device_init(bus, card, codec_addr, codecp);
+ if (ret < 0)
+ return ret;
+
+ return snd_hda_codec_device_new(bus, card, codec_addr, *codecp);
+}
+EXPORT_SYMBOL_GPL(snd_hda_codec_new);
+
+int snd_hda_codec_device_new(struct hda_bus *bus, struct snd_card *card,
+ unsigned int codec_addr, struct hda_codec *codec)
+{
char component[31];
hda_nid_t fg;
int err;
@@ -879,25 +924,14 @@ int snd_hda_codec_new(struct hda_bus *bus, struct snd_card *card,
.dev_free = snd_hda_codec_dev_free,
};
+ dev_dbg(card->dev, "%s: entry\n", __func__);
+
if (snd_BUG_ON(!bus))
return -EINVAL;
if (snd_BUG_ON(codec_addr > HDA_MAX_CODEC_ADDRESS))
return -EINVAL;
- codec = kzalloc(sizeof(*codec), GFP_KERNEL);
- if (!codec)
- return -ENOMEM;
-
- sprintf(component, "hdaudioC%dD%d", card->number, codec_addr);
- err = snd_hdac_device_init(&codec->core, &bus->core, component,
- codec_addr);
- if (err < 0) {
- kfree(codec);
- return err;
- }
-
codec->core.dev.release = snd_hda_codec_dev_release;
- codec->core.type = HDA_DEV_LEGACY;
codec->core.exec_verb = codec_exec_verb;
codec->bus = bus;
@@ -957,15 +991,13 @@ int snd_hda_codec_new(struct hda_bus *bus, struct snd_card *card,
if (err < 0)
goto error;
- if (codecp)
- *codecp = codec;
return 0;
error:
put_device(hda_codec_dev(codec));
return err;
}
-EXPORT_SYMBOL_GPL(snd_hda_codec_new);
+EXPORT_SYMBOL_GPL(snd_hda_codec_device_new);
/**
* snd_hda_codec_update_widgets - Refresh widget caps and pin defaults
@@ -2992,6 +3024,7 @@ int snd_hda_codec_build_controls(struct hda_codec *codec)
sync_power_up_states(codec);
return 0;
}
+EXPORT_SYMBOL_GPL(snd_hda_codec_build_controls);
/*
* PCM stuff
@@ -3197,6 +3230,7 @@ int snd_hda_codec_parse_pcms(struct hda_codec *codec)
return 0;
}
+EXPORT_SYMBOL_GPL(snd_hda_codec_parse_pcms);
/* assign all PCMs of the given codec */
int snd_hda_codec_build_pcms(struct hda_codec *codec)
diff --git a/sound/pci/hda/hda_codec.h b/sound/pci/hda/hda_codec.h
index a8b1b31f161c..e03b5c1ccc5c 100644
--- a/sound/pci/hda/hda_codec.h
+++ b/sound/pci/hda/hda_codec.h
@@ -308,6 +308,8 @@ struct hda_codec {
*/
int snd_hda_codec_new(struct hda_bus *bus, struct snd_card *card,
unsigned int codec_addr, struct hda_codec **codecp);
+int snd_hda_codec_device_new(struct hda_bus *bus, struct snd_card *card,
+ unsigned int codec_addr, struct hda_codec *codec);
int snd_hda_codec_configure(struct hda_codec *codec);
int snd_hda_codec_update_widgets(struct hda_codec *codec);
diff --git a/sound/pci/hda/patch_hdmi.c b/sound/pci/hda/patch_hdmi.c
index 8a49415aebac..1de5491fb9bf 100644
--- a/sound/pci/hda/patch_hdmi.c
+++ b/sound/pci/hda/patch_hdmi.c
@@ -177,13 +177,13 @@ struct hdmi_spec {
/* i915/powerwell (Haswell+/Valleyview+) specific */
bool use_acomp_notifier; /* use i915 eld_notify callback for hotplug */
- struct i915_audio_component_audio_ops i915_audio_ops;
+ struct drm_audio_component_audio_ops drm_audio_ops;
struct hdac_chmap chmap;
hda_nid_t vendor_nid;
};
-#ifdef CONFIG_SND_HDA_I915
+#ifdef CONFIG_SND_HDA_COMPONENT
static inline bool codec_has_acomp(struct hda_codec *codec)
{
struct hdmi_spec *spec = codec->spec;
@@ -2288,7 +2288,7 @@ static void generic_hdmi_free(struct hda_codec *codec)
int pin_idx, pcm_idx;
if (codec_has_acomp(codec))
- snd_hdac_i915_register_notifier(NULL);
+ snd_hdac_acomp_register_notifier(&codec->bus->core, NULL);
for (pin_idx = 0; pin_idx < spec->num_pins; pin_idx++) {
struct hdmi_spec_per_pin *per_pin = get_pin(spec, pin_idx);
@@ -2471,6 +2471,38 @@ static void haswell_set_power_state(struct hda_codec *codec, hda_nid_t fg,
snd_hda_codec_set_power_to_all(codec, fg, power_state);
}
+/* There is a fixed mapping between audio pin node and display port.
+ * on SNB, IVY, HSW, BSW, SKL, BXT, KBL:
+ * Pin Widget 5 - PORT B (port = 1 in i915 driver)
+ * Pin Widget 6 - PORT C (port = 2 in i915 driver)
+ * Pin Widget 7 - PORT D (port = 3 in i915 driver)
+ *
+ * on VLV, ILK:
+ * Pin Widget 4 - PORT B (port = 1 in i915 driver)
+ * Pin Widget 5 - PORT C (port = 2 in i915 driver)
+ * Pin Widget 6 - PORT D (port = 3 in i915 driver)
+ */
+static int intel_base_nid(struct hda_codec *codec)
+{
+ switch (codec->core.vendor_id) {
+ case 0x80860054: /* ILK */
+ case 0x80862804: /* ILK */
+ case 0x80862882: /* VLV */
+ return 4;
+ default:
+ return 5;
+ }
+}
+
+static int intel_pin2port(void *audio_ptr, int pin_nid)
+{
+ int base_nid = intel_base_nid(audio_ptr);
+
+ if (WARN_ON(pin_nid < base_nid || pin_nid >= base_nid + 3))
+ return -1;
+ return pin_nid - base_nid + 1; /* intel port is 1-based */
+}
+
static void intel_pin_eld_notify(void *audio_ptr, int port, int pipe)
{
struct hda_codec *codec = audio_ptr;
@@ -2481,16 +2513,7 @@ static void intel_pin_eld_notify(void *audio_ptr, int port, int pipe)
if (port < 1 || port > 3)
return;
- switch (codec->core.vendor_id) {
- case 0x80860054: /* ILK */
- case 0x80862804: /* ILK */
- case 0x80862882: /* VLV */
- pin_nid = port + 0x03;
- break;
- default:
- pin_nid = port + 0x04;
- break;
- }
+ pin_nid = port + intel_base_nid(codec) - 1; /* intel port is 1-based */
/* skip notification during system suspend (but not in runtime PM);
* the state will be updated at resume
@@ -2511,14 +2534,16 @@ static void register_i915_notifier(struct hda_codec *codec)
struct hdmi_spec *spec = codec->spec;
spec->use_acomp_notifier = true;
- spec->i915_audio_ops.audio_ptr = codec;
+ spec->drm_audio_ops.audio_ptr = codec;
/* intel_audio_codec_enable() or intel_audio_codec_disable()
* will call pin_eld_notify with using audio_ptr pointer
* We need make sure audio_ptr is really setup
*/
wmb();
- spec->i915_audio_ops.pin_eld_notify = intel_pin_eld_notify;
- snd_hdac_i915_register_notifier(&spec->i915_audio_ops);
+ spec->drm_audio_ops.pin2port = intel_pin2port;
+ spec->drm_audio_ops.pin_eld_notify = intel_pin_eld_notify;
+ snd_hdac_acomp_register_notifier(&codec->bus->core,
+ &spec->drm_audio_ops);
}
/* setup_stream ops override for HSW+ */