All of lore.kernel.org
 help / color / mirror / Atom feed
From: Pierre-Louis Bossart <pierre-louis.bossart@linux.intel.com>
To: alsa-devel@alsa-project.org
Subject: Re: ALSA: hda: hdmi: Hint matching between input devices and pcm devices
Date: Mon, 29 Aug 2011 17:14:23 -0500	[thread overview]
Message-ID: <1314656063.27660.9.camel@plb-Dell> (raw)
In-Reply-To: <4E56C088.6080402@canonical.com>

[-- Attachment #1: Type: text/plain, Size: 807 bytes --]


> Since modern HDMI cards often have more than one output pin and thus
> input device, we need to know which one has actually been plugged in.
> This patch adds a name hint that indicates which PCM device is connected
> to which pin.

I've been thinking about this, and there's some additional work needed
for the jack-detection to be useful.
User-space code will need at some point to rely on the ELD information
to know what the HDMI receiver supports, eg to enable/disable
passthrough. I hacked a while ago a small patch to make the ELD bytes
available in a control (see attached). It seems to work but I wasn't too
sure how to expose it. 
Should we define a convention for the name of this control as well? Or
is there a way to link a control to a specify PCM device?
Thanks for your feedback,
-Pierre

[-- Attachment #2: eld.patch --]
[-- Type: text/x-patch, Size: 4819 bytes --]

diff --git a/sound/pci/hda/hda_eld.c b/sound/pci/hda/hda_eld.c
index 28ce17d..01d5226 100644
--- a/sound/pci/hda/hda_eld.c
+++ b/sound/pci/hda/hda_eld.c
@@ -24,6 +24,8 @@
 #include <linux/init.h>
 #include <linux/slab.h>
 #include <sound/core.h>
+#include <sound/control.h>
+#include <sound/asoundef.h>
 #include <asm/unaligned.h>
 #include "hda_codec.h"
 #include "hda_local.h"
@@ -318,6 +320,14 @@ int snd_hdmi_get_eld_size(struct hda_codec *codec, hda_nid_t nid)
 						 AC_DIPSIZE_ELD_BUF);
 }
 
+
+static struct snd_kcontrol_new eld_bytes_ctl = {
+	.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
+	.name = "ELD Bytes",
+	.info = snd_hdmi_eld_ctl_info,
+	.get = snd_hdmi_eld_ctl_get
+};
+
 int snd_hdmi_get_eld(struct hdmi_eld *eld,
 		     struct hda_codec *codec, hda_nid_t nid)
 {
@@ -325,6 +335,8 @@ int snd_hdmi_get_eld(struct hdmi_eld *eld,
 	int ret;
 	int size;
 	unsigned char *buf;
+	struct snd_kcontrol *kctl;
+	int err;
 
 	if (!eld->eld_valid)
 		return -ENOENT;
@@ -335,21 +347,30 @@ int snd_hdmi_get_eld(struct hdmi_eld *eld,
 		snd_printd(KERN_INFO "HDMI: ELD buf size is 0, force 128\n");
 		size = 128;
 	}
-	if (size < ELD_FIXED_BYTES || size > PAGE_SIZE) {
+	if (size < ELD_FIXED_BYTES || size > ELD_MAX_SIZE || size > PAGE_SIZE) {
 		snd_printd(KERN_INFO "HDMI: invalid ELD buf size %d\n", size);
 		return -ERANGE;
 	}
 
-	buf = kmalloc(size, GFP_KERNEL);
-	if (!buf)
+	/* add control for ELD Bytes */
+	kctl = snd_ctl_new1(&eld_bytes_ctl, codec);
+	if (!kctl)
 		return -ENOMEM;
+	err = snd_hda_ctl_add(codec, nid, kctl);
+	if (err < 0)
+		return err;
+	kctl->private_value = nid;
+	printk(KERN_ERR "plb: added control \n");
+
+	/* update info */
+	eld->eld_size = size;
+	buf = eld->eld_buffer;
 
 	for (i = 0; i < size; i++)
 		buf[i] = hdmi_get_eld_byte(codec, nid, i);
 
 	ret = hdmi_update_eld(eld, buf, size);
 
-	kfree(buf);
 	return ret;
 }
 
diff --git a/sound/pci/hda/hda_local.h b/sound/pci/hda/hda_local.h
index 9ed4b0d..1f237ef 100644
--- a/sound/pci/hda/hda_local.h
+++ b/sound/pci/hda/hda_local.h
@@ -609,6 +609,7 @@ struct cea_sad {
 };
 
 #define ELD_FIXED_BYTES	20
+#define ELD_MAX_SIZE    256
 #define ELD_MAX_MNL	16
 #define ELD_MAX_SAD	16
 
@@ -633,6 +634,7 @@ struct hdmi_eld {
 	int	spk_alloc;
 	int	sad_count;
 	struct cea_sad sad[ELD_MAX_SAD];
+	char    eld_buffer[ELD_MAX_SIZE];
 #ifdef CONFIG_PROC_FS
 	struct snd_info_entry *proc_entry;
 #endif
@@ -643,6 +645,10 @@ int snd_hdmi_get_eld(struct hdmi_eld *, struct hda_codec *, hda_nid_t);
 void snd_hdmi_show_eld(struct hdmi_eld *eld);
 void snd_hdmi_eld_update_pcm_info(struct hdmi_eld *eld,
 			      struct hda_pcm_stream *hinfo);
+int snd_hdmi_eld_ctl_info(struct snd_kcontrol *kcontrol,
+			struct snd_ctl_elem_info *uinfo);
+int snd_hdmi_eld_ctl_get(struct snd_kcontrol *kcontrol,
+			struct snd_ctl_elem_value *ucontrol);
 
 #ifdef CONFIG_PROC_FS
 int snd_hda_eld_proc_new(struct hda_codec *codec, struct hdmi_eld *eld,
diff --git a/sound/pci/hda/patch_hdmi.c b/sound/pci/hda/patch_hdmi.c
index 19cb72d..4a11e93 100644
--- a/sound/pci/hda/patch_hdmi.c
+++ b/sound/pci/hda/patch_hdmi.c
@@ -324,6 +324,62 @@ static int cvt_nid_to_cvt_index(struct hdmi_spec *spec, hda_nid_t cvt_nid)
 	return -EINVAL;
 }
 
+int snd_hdmi_eld_ctl_info(struct snd_kcontrol *kcontrol,
+			struct snd_ctl_elem_info *uinfo)
+{
+	struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
+	struct hdmi_spec *spec;
+	struct hdmi_spec_per_pin *per_pin;
+	struct hdmi_eld *eld;
+	int pin_nid;
+	int pin_idx;
+
+	printk(KERN_ERR "plb: in ctl_info routine\n");
+	uinfo->type = SNDRV_CTL_ELEM_TYPE_BYTES;
+
+	pin_nid = kcontrol->private_value;
+	spec = codec->spec;
+
+	pin_idx = pin_nid_to_pin_index(spec, pin_nid);
+	if (pin_idx<0) {
+		uinfo->count = 0;
+	} else {
+		per_pin = &spec->pins[pin_idx];
+		eld = &per_pin->sink_eld;
+		uinfo->count = eld->eld_size;
+	}
+	return 0;
+}
+
+int snd_hdmi_eld_ctl_get(struct snd_kcontrol *kcontrol,
+			struct snd_ctl_elem_value *ucontrol)
+{
+	struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
+	struct hdmi_spec *spec;
+	struct hdmi_spec_per_pin *per_pin;
+	struct hdmi_eld *eld;
+	int pin_nid;
+	int pin_idx;
+
+	printk(KERN_ERR "plb: in ctl_get routine\n");
+	pin_nid = kcontrol->private_value;
+
+	spec = codec->spec;
+	pin_nid = kcontrol->private_value;
+
+	pin_idx = pin_nid_to_pin_index(spec, pin_nid);
+	if (pin_idx<0) {
+		memset(ucontrol->value.bytes.data, 0, ELD_MAX_SIZE);
+		printk(KERN_ERR "eld_get: no info found\n");
+	} else {
+		per_pin = &spec->pins[pin_idx];
+		eld = &per_pin->sink_eld;
+		printk(KERN_ERR "eld_get: copying %d bytes\n", eld->eld_size);
+		memcpy(ucontrol->value.bytes.data, eld->eld_buffer, eld->eld_size);
+	}
+	return 0;
+}
+
 #ifdef BE_PARANOID
 static void hdmi_get_dip_index(struct hda_codec *codec, hda_nid_t pin_nid,
 				int *packet_index, int *byte_index)

[-- Attachment #3: Type: text/plain, Size: 0 bytes --]



  reply	other threads:[~2011-08-29 22:14 UTC|newest]

Thread overview: 12+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2011-08-23 15:11 ALSA: hda: hdmi: Hint matching between input devices and pcm devices David Henningsson
2011-08-23 15:51 ` Stephen Warren
2011-08-24  4:53   ` David Henningsson
2011-08-24 21:21     ` Stephen Warren
2011-08-25  7:13       ` David Henningsson
2011-08-25 17:41         ` Stephen Warren
2011-08-25 21:37           ` David Henningsson
2011-08-29 22:14             ` Pierre-Louis Bossart [this message]
2011-08-30  7:06               ` David Henningsson
2011-08-30  7:40               ` Clemens Ladisch
2011-08-30 13:01                 ` Pierre-Louis Bossart
     [not found]                 ` <000601cc6714$fc5caa80$f515ff80$@bossart@linux.intel.com>
2011-09-12  7:10                   ` Takashi Iwai

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=1314656063.27660.9.camel@plb-Dell \
    --to=pierre-louis.bossart@linux.intel.com \
    --cc=alsa-devel@alsa-project.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.