Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 9b3dc8aa authored by Subhransu S. Prusty's avatar Subhransu S. Prusty Committed by Takashi Iwai
Browse files

ALSA: hda - Register chmap obj as priv data instead of codec



With this chmap object is added as private data and new ops are
added to access driver specific chmap.

Signed-off-by: default avatarSubhransu S. Prusty <subhransu.s.prusty@intel.com>
Signed-off-by: default avatarVinod Koul <vinod.koul@intel.com>
Signed-off-by: default avatarTakashi Iwai <tiwai@suse.de>
parent 67b90cb8
Loading
Loading
Loading
Loading
+6 −0
Original line number Diff line number Diff line
@@ -30,6 +30,12 @@ struct hdac_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_pcm_attached)(struct hdac_device *hdac, int pcm_idx);
};

struct hdac_chmap {
+59 −34
Original line number Diff line number Diff line
@@ -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 hdac_chmap *chmap = &spec->chmap;
	struct hdac_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_pcm_attached(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 hdac_chmap *chmap = &spec->chmap;
	struct hdac_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 hdac_chmap *chmap = &spec->chmap;
	struct hdac_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 hdac_chmap *hchmap = &spec->chmap;
	struct hdac_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_pcm_attached(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 hdac_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_pcm_attached			= is_hdmi_pcm_attached,
};


static void intel_haswell_fixup_connect_list(struct hda_codec *codec,
					     hda_nid_t nid)
{