diff mbox

[v2,2/7] ALSA: hda - Register chmap obj as priv data instead of codec

Message ID 1456920208-1172-3-git-send-email-subhransu.s.prusty@intel.com (mailing list archive)
State New, archived
Headers show

Commit Message

Subhransu S. Prusty March 2, 2016, 12:03 p.m. UTC
With this chmap object is added as private data and new ops are
added to access driver specific chmap.

Signed-off-by: Subhransu S. Prusty <subhransu.s.prusty@intel.com>
Signed-off-by: Vinod Koul <vinod.koul@intel.com>
---
 include/sound/hdmi_chmap.h |   6 +++
 sound/pci/hda/patch_hdmi.c | 100 ++++++++++++++++++++++++++++++---------------
 2 files changed, 72 insertions(+), 34 deletions(-)

Comments

Takashi Iwai March 2, 2016, 4:05 p.m. UTC | #1
On Wed, 02 Mar 2016 13:03:23 +0100,
Subhransu S. Prusty wrote:
> 
> With this chmap object is added as private data and new ops are
> added to access driver specific chmap.
> 
> Signed-off-by: Subhransu S. Prusty <subhransu.s.prusty@intel.com>
> Signed-off-by: Vinod Koul <vinod.koul@intel.com>
> ---
>  include/sound/hdmi_chmap.h |   6 +++
>  sound/pci/hda/patch_hdmi.c | 100 ++++++++++++++++++++++++++++++---------------
>  2 files changed, 72 insertions(+), 34 deletions(-)
> 
> diff --git a/include/sound/hdmi_chmap.h b/include/sound/hdmi_chmap.h
> index 32087f1..c7702ef9 100644
> --- a/include/sound/hdmi_chmap.h
> +++ b/include/sound/hdmi_chmap.h
> @@ -30,6 +30,12 @@ struct hdmi_chmap_ops {
>  
>  	/* check that the user-given chmap is supported */
>  	int (*chmap_validate)(int ca, int channels, unsigned char *chmap);
> +
> +	void (*get_chmap)(struct hdac_device *hdac, int pcm_idx,
> +					unsigned char *chmap);
> +	void (*set_chmap)(struct hdac_device *hdac, int pcm_idx,
> +			unsigned char *chmap, int prepared);
> +	bool (*is_monitor_connected)(struct hdac_device *hdac, int pcm_idx);

This name is rather confusing.  Actually, this function doesn't mean
the monitor connected state.  It indicates rather whether any pin is
assigned to the given PCM.  It may return false only for devices with
dynamic PCM assignment.  For the rest, it's always true.


Takashi
diff mbox

Patch

diff --git a/include/sound/hdmi_chmap.h b/include/sound/hdmi_chmap.h
index 32087f1..c7702ef9 100644
--- a/include/sound/hdmi_chmap.h
+++ b/include/sound/hdmi_chmap.h
@@ -30,6 +30,12 @@  struct hdmi_chmap_ops {
 
 	/* check that the user-given chmap is supported */
 	int (*chmap_validate)(int ca, int channels, unsigned char *chmap);
+
+	void (*get_chmap)(struct hdac_device *hdac, int pcm_idx,
+					unsigned char *chmap);
+	void (*set_chmap)(struct hdac_device *hdac, int pcm_idx,
+			unsigned char *chmap, int prepared);
+	bool (*is_monitor_connected)(struct hdac_device *hdac, int pcm_idx);
 };
 
 struct hdmi_chmap {
diff --git a/sound/pci/hda/patch_hdmi.c b/sound/pci/hda/patch_hdmi.c
index fd5ae6f..ed51d0d 100644
--- a/sound/pci/hda/patch_hdmi.c
+++ b/sound/pci/hda/patch_hdmi.c
@@ -100,8 +100,6 @@  struct hdmi_spec_per_pin {
 #endif
 };
 
-struct cea_channel_speaker_allocation;
-
 /* operations used by generic code that can be overridden by patches */
 struct hdmi_ops {
 	int (*pin_get_eld)(struct hda_codec *codec, hda_nid_t pin_nid,
@@ -2350,9 +2348,7 @@  static int hdmi_chmap_ctl_info(struct snd_kcontrol *kcontrol,
 			       struct snd_ctl_elem_info *uinfo)
 {
 	struct snd_pcm_chmap *info = snd_kcontrol_chip(kcontrol);
-	struct hda_codec *codec = info->private_data;
-	struct hdmi_spec *spec = codec->spec;
-	struct hdmi_chmap *chmap = &spec->chmap;
+	struct hdmi_chmap *chmap = info->private_data;
 
 	uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
 	uinfo->count = chmap->channels_max;
@@ -2389,13 +2385,49 @@  static void hdmi_cea_alloc_to_tlv_chmap(struct cea_channel_speaker_allocation *c
 	WARN_ON(count != channels);
 }
 
+static void hdmi_get_chmap(struct hdac_device *hdac, int pcm_idx,
+					unsigned char *chmap)
+{
+	struct hda_codec *codec = container_of(hdac, struct hda_codec, core);
+	struct hdmi_spec *spec = codec->spec;
+	struct hdmi_spec_per_pin *per_pin = pcm_idx_to_pin(spec, pcm_idx);
+
+	/* chmap is already set to 0 in caller */
+	if (!per_pin)
+		return;
+
+	memcpy(chmap, per_pin->chmap, ARRAY_SIZE(per_pin->chmap));
+}
+
+static void hdmi_set_chmap(struct hdac_device *hdac, int pcm_idx,
+				unsigned char *chmap, int prepared)
+{
+	struct hda_codec *codec = container_of(hdac, struct hda_codec, core);
+	struct hdmi_spec *spec = codec->spec;
+	struct hdmi_spec_per_pin *per_pin = pcm_idx_to_pin(spec, pcm_idx);
+
+	mutex_lock(&per_pin->lock);
+	per_pin->chmap_set = true;
+	memcpy(per_pin->chmap, chmap, ARRAY_SIZE(per_pin->chmap));
+	if (prepared)
+		hdmi_setup_audio_infoframe(codec, per_pin, per_pin->non_pcm);
+	mutex_unlock(&per_pin->lock);
+}
+
+static bool is_hdmi_monitor_connected(struct hdac_device *hdac, int pcm_idx)
+{
+	struct hda_codec *codec = container_of(hdac, struct hda_codec, core);
+	struct hdmi_spec *spec = codec->spec;
+	struct hdmi_spec_per_pin *per_pin = pcm_idx_to_pin(spec, pcm_idx);
+
+	return per_pin ? true:false;
+}
+
 static int hdmi_chmap_ctl_tlv(struct snd_kcontrol *kcontrol, int op_flag,
 			      unsigned int size, unsigned int __user *tlv)
 {
 	struct snd_pcm_chmap *info = snd_kcontrol_chip(kcontrol);
-	struct hda_codec *codec = info->private_data;
-	struct hdmi_spec *spec = codec->spec;
-	struct hdmi_chmap *chmap = &spec->chmap;
+	struct hdmi_chmap *chmap = info->private_data;
 	unsigned int __user *dst;
 	int chs, count = 0;
 
@@ -2444,21 +2476,17 @@  static int hdmi_chmap_ctl_get(struct snd_kcontrol *kcontrol,
 			      struct snd_ctl_elem_value *ucontrol)
 {
 	struct snd_pcm_chmap *info = snd_kcontrol_chip(kcontrol);
-	struct hda_codec *codec = info->private_data;
-	struct hdmi_spec *spec = codec->spec;
-	struct hdmi_chmap *chmap = &spec->chmap;
+	struct hdmi_chmap *chmap = info->private_data;
 	int pcm_idx = kcontrol->private_value;
-	struct hdmi_spec_per_pin *per_pin = pcm_idx_to_pin(spec, pcm_idx);
+	unsigned char pcm_chmap[8];
 	int i;
 
-	if (!per_pin) {
-		for (i = 0; i < chmap->channels_max; i++)
-			ucontrol->value.integer.value[i] = 0;
-		return 0;
-	}
+	memset(pcm_chmap, 0, sizeof(pcm_chmap));
+	chmap->ops.get_chmap(chmap->hdac, pcm_idx, pcm_chmap);
+
+	for (i = 0; i < sizeof(chmap); i++)
+		ucontrol->value.integer.value[i] = pcm_chmap[i];
 
-	for (i = 0; i < ARRAY_SIZE(per_pin->chmap); i++)
-		ucontrol->value.integer.value[i] = per_pin->chmap[i];
 	return 0;
 }
 
@@ -2466,20 +2494,17 @@  static int hdmi_chmap_ctl_put(struct snd_kcontrol *kcontrol,
 			      struct snd_ctl_elem_value *ucontrol)
 {
 	struct snd_pcm_chmap *info = snd_kcontrol_chip(kcontrol);
-	struct hda_codec *codec = info->private_data;
-	struct hdmi_spec *spec = codec->spec;
-	struct hdmi_chmap *hchmap = &spec->chmap;
+	struct hdmi_chmap *hchmap = info->private_data;
 	int pcm_idx = kcontrol->private_value;
-	struct hdmi_spec_per_pin *per_pin = pcm_idx_to_pin(spec, pcm_idx);
 	unsigned int ctl_idx;
 	struct snd_pcm_substream *substream;
-	unsigned char chmap[8];
+	unsigned char chmap[8], per_pin_chmap[8];
 	int i, err, ca, prepared = 0;
 
 	/* No monitor is connected in dyn_pcm_assign.
 	 * It's invalid to setup the chmap
 	 */
-	if (!per_pin)
+	if (!hchmap->ops.is_monitor_connected(hchmap->hdac, pcm_idx))
 		return 0;
 
 	ctl_idx = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id);
@@ -2499,7 +2524,9 @@  static int hdmi_chmap_ctl_put(struct snd_kcontrol *kcontrol,
 	memset(chmap, 0, sizeof(chmap));
 	for (i = 0; i < ARRAY_SIZE(chmap); i++)
 		chmap[i] = ucontrol->value.integer.value[i];
-	if (!memcmp(chmap, per_pin->chmap, sizeof(chmap)))
+
+	hchmap->ops.get_chmap(hchmap->hdac, pcm_idx, per_pin_chmap);
+	if (!memcmp(chmap, per_pin_chmap, sizeof(chmap)))
 		return 0;
 	ca = hdmi_manual_channel_allocation(ARRAY_SIZE(chmap), chmap);
 	if (ca < 0)
@@ -2509,12 +2536,8 @@  static int hdmi_chmap_ctl_put(struct snd_kcontrol *kcontrol,
 		if (err)
 			return err;
 	}
-	mutex_lock(&per_pin->lock);
-	per_pin->chmap_set = true;
-	memcpy(per_pin->chmap, chmap, sizeof(chmap));
-	if (prepared)
-		hdmi_setup_audio_infoframe(codec, per_pin, per_pin->non_pcm);
-	mutex_unlock(&per_pin->lock);
+
+	hchmap->ops.set_chmap(hchmap->hdac, pcm_idx, chmap, prepared);
 
 	return 0;
 }
@@ -2672,7 +2695,7 @@  static int generic_hdmi_build_controls(struct hda_codec *codec)
 		if (err < 0)
 			return err;
 		/* override handlers */
-		chmap->private_data = codec;
+		chmap->private_data = &spec->chmap;
 		kctl = chmap->kctl;
 		for (i = 0; i < kctl->count; i++)
 			kctl->vd[i].access |= SNDRV_CTL_ELEM_ACCESS_WRITE;
@@ -2801,9 +2824,11 @@  static const struct hdmi_ops generic_standard_hdmi_ops = {
 static const struct hdmi_chmap_ops chmap_ops = {
 	.chmap_cea_alloc_validate_get_type	= hdmi_chmap_cea_alloc_validate_get_type,
 	.cea_alloc_to_tlv_chmap			= hdmi_cea_alloc_to_tlv_chmap,
+	.get_chmap				= hdmi_get_chmap,
+	.set_chmap				= hdmi_set_chmap,
+	.is_monitor_connected			= is_hdmi_monitor_connected,
 };
 
-
 static void intel_haswell_fixup_connect_list(struct hda_codec *codec,
 					     hda_nid_t nid)
 {
@@ -3526,6 +3551,9 @@  static int patch_nvhdmi(struct hda_codec *codec)
 	spec->chmap.ops.chmap_cea_alloc_validate_get_type =
 		nvhdmi_chmap_cea_alloc_validate_get_type;
 	spec->chmap.ops.chmap_validate = nvhdmi_chmap_validate;
+	spec->chmap.ops.get_chmap = hdmi_get_chmap;
+	spec->chmap.ops.set_chmap = hdmi_set_chmap;
+	spec->chmap.ops.is_monitor_connected = is_hdmi_monitor_connected;
 
 	return 0;
 }
@@ -4039,6 +4067,10 @@  static int patch_atihdmi(struct hda_codec *codec)
 		spec->chmap.ops.cea_alloc_to_tlv_chmap =
 				atihdmi_paired_cea_alloc_to_tlv_chmap;
 		spec->chmap.ops.chmap_validate = atihdmi_paired_chmap_validate;
+		spec->chmap.ops.get_chmap = hdmi_get_chmap;
+		spec->chmap.ops.set_chmap = hdmi_set_chmap;
+		spec->chmap.ops.is_monitor_connected =
+				is_hdmi_monitor_connected;
 	}
 
 	/* ATI/AMD converters do not advertise all of their capabilities */