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

Commit 828cb4ed authored by Subhransu S. Prusty's avatar Subhransu S. Prusty Committed by Takashi Iwai
Browse files

ALSA: hda - chmap helper args modified to use generic hdac objs.



Chmap helper arguments are modified to use either hdac_device
object or hdac_chmap object instead of codec specific object.
With this moving these APIs to core will be easier.

Helper added to access a specific channel_allocation object
instead of directly accessing.

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 739ffee9
Loading
Loading
Loading
Loading
+7 −3
Original line number Original line Diff line number Diff line
@@ -7,6 +7,9 @@


#include <sound/hdaudio.h>
#include <sound/hdaudio.h>



#define SND_PRINT_CHANNEL_ALLOCATION_ADVISED_BUFSIZE 80

struct hdac_cea_channel_speaker_allocation {
struct hdac_cea_channel_speaker_allocation {
	int ca_index;
	int ca_index;
	int speakers[8];
	int speakers[8];
@@ -24,12 +27,13 @@ struct hdac_chmap_ops {
	 */
	 */
	int (*chmap_cea_alloc_validate_get_type)(struct hdac_chmap *chmap,
	int (*chmap_cea_alloc_validate_get_type)(struct hdac_chmap *chmap,
		struct hdac_cea_channel_speaker_allocation *cap, int channels);
		struct hdac_cea_channel_speaker_allocation *cap, int channels);
	void (*cea_alloc_to_tlv_chmap)
	void (*cea_alloc_to_tlv_chmap)(struct hdac_chmap *hchmap,
		(struct hdac_cea_channel_speaker_allocation *cap,
		struct hdac_cea_channel_speaker_allocation *cap,
		unsigned int *chmap, int channels);
		unsigned int *chmap, int channels);


	/* check that the user-given chmap is supported */
	/* check that the user-given chmap is supported */
	int (*chmap_validate)(int ca, int channels, unsigned char *chmap);
	int (*chmap_validate)(struct hdac_chmap *hchmap, int ca,
			int channels, unsigned char *chmap);


	void (*get_chmap)(struct hdac_device *hdac, int pcm_idx,
	void (*get_chmap)(struct hdac_device *hdac, int pcm_idx,
					unsigned char *chmap);
					unsigned char *chmap);
+67 −41
Original line number Original line Diff line number Diff line
@@ -696,8 +696,8 @@ static int get_channel_allocation_order(int ca)
 *
 *
 * TODO: it could select the wrong CA from multiple candidates.
 * TODO: it could select the wrong CA from multiple candidates.
*/
*/
static int hdmi_channel_allocation(struct hda_codec *codec,
static int hdmi_channel_allocation_spk_alloc_blk(struct hdac_device *codec,
				   struct hdmi_eld *eld, int channels)
				   int spk_alloc, int channels)
{
{
	int i;
	int i;
	int ca = 0;
	int ca = 0;
@@ -717,7 +717,7 @@ static int hdmi_channel_allocation(struct hda_codec *codec,
	 * expand ELD's notions to match the ones used by Audio InfoFrame.
	 * expand ELD's notions to match the ones used by Audio InfoFrame.
	 */
	 */
	for (i = 0; i < ARRAY_SIZE(eld_speaker_allocation_bits); i++) {
	for (i = 0; i < ARRAY_SIZE(eld_speaker_allocation_bits); i++) {
		if (eld->info.spk_alloc & (1 << i))
		if (spk_alloc & (1 << i))
			spk_mask |= eld_speaker_allocation_bits[i];
			spk_mask |= eld_speaker_allocation_bits[i];
	}
	}


@@ -742,36 +742,34 @@ static int hdmi_channel_allocation(struct hda_codec *codec,
		}
		}
	}
	}


	snd_print_channel_allocation(eld->info.spk_alloc, buf, sizeof(buf));
	snd_print_channel_allocation(spk_alloc, buf, sizeof(buf));
	codec_dbg(codec, "HDMI: select CA 0x%x for %d-channel allocation: %s\n",
	dev_dbg(&codec->dev, "HDMI: select CA 0x%x for %d-channel allocation: %s\n",
		    ca, channels, buf);
		    ca, channels, buf);


	return ca;
	return ca;
}
}


static void hdmi_debug_channel_mapping(struct hda_codec *codec,
static void hdmi_debug_channel_mapping(struct hdac_chmap *chmap,
				       hda_nid_t pin_nid)
				       hda_nid_t pin_nid)
{
{
#ifdef CONFIG_SND_DEBUG_VERBOSE
#ifdef CONFIG_SND_DEBUG_VERBOSE
	struct hdmi_spec *spec = codec->spec;
	int i;
	int i;
	int channel;
	int channel;


	for (i = 0; i < 8; i++) {
	for (i = 0; i < 8; i++) {
		channel = spec->chmap.ops.pin_get_slot_channel(
		channel = chmap->ops.pin_get_slot_channel(
				&codec->core, pin_nid, i);
				chmap->hdac, pin_nid, i);
		codec_dbg(codec, "HDMI: ASP channel %d => slot %d\n",
		dev_dbg(&chmap->hdac->dev, "HDMI: ASP channel %d => slot %d\n",
						channel, i);
						channel, i);
	}
	}
#endif
#endif
}
}


static void hdmi_std_setup_channel_mapping(struct hda_codec *codec,
static void hdmi_std_setup_channel_mapping(struct hdac_chmap *chmap,
				       hda_nid_t pin_nid,
				       hda_nid_t pin_nid,
				       bool non_pcm,
				       bool non_pcm,
				       int ca)
				       int ca)
{
{
	struct hdmi_spec *spec = codec->spec;
	struct hdac_cea_channel_speaker_allocation *ch_alloc;
	struct hdac_cea_channel_speaker_allocation *ch_alloc;
	int i;
	int i;
	int err;
	int err;
@@ -807,10 +805,10 @@ static void hdmi_std_setup_channel_mapping(struct hda_codec *codec,
		int slotsetup = non_pcm ? non_pcm_mapping[i] : hdmi_channel_mapping[ca][i];
		int slotsetup = non_pcm ? non_pcm_mapping[i] : hdmi_channel_mapping[ca][i];
		int hdmi_slot = slotsetup & 0x0f;
		int hdmi_slot = slotsetup & 0x0f;
		int channel = (slotsetup & 0xf0) >> 4;
		int channel = (slotsetup & 0xf0) >> 4;
		err = spec->chmap.ops.pin_set_slot_channel(
		err = chmap->ops.pin_set_slot_channel(chmap->hdac,
				&codec->core, pin_nid, hdmi_slot, channel);
				pin_nid, hdmi_slot, channel);
		if (err) {
		if (err) {
			codec_dbg(codec, "HDMI: channel mapping failed\n");
			dev_dbg(&chmap->hdac->dev, "HDMI: channel mapping failed\n");
			break;
			break;
		}
		}
	}
	}
@@ -912,12 +910,11 @@ static int hdmi_manual_channel_allocation(int chs, unsigned char *map)
}
}


/* set up the channel slots for the given ALSA API channel map */
/* set up the channel slots for the given ALSA API channel map */
static int hdmi_manual_setup_channel_mapping(struct hda_codec *codec,
static int hdmi_manual_setup_channel_mapping(struct hdac_chmap *chmap,
					     hda_nid_t pin_nid,
					     hda_nid_t pin_nid,
					     int chs, unsigned char *map,
					     int chs, unsigned char *map,
					     int ca)
					     int ca)
{
{
	struct hdmi_spec *spec = codec->spec;
	int ordered_ca = get_channel_allocation_order(ca);
	int ordered_ca = get_channel_allocation_order(ca);
	int alsa_pos, hdmi_slot;
	int alsa_pos, hdmi_slot;
	int assignments[8] = {[0 ... 7] = 0xf};
	int assignments[8] = {[0 ... 7] = 0xf};
@@ -935,7 +932,7 @@ static int hdmi_manual_setup_channel_mapping(struct hda_codec *codec,
	for (hdmi_slot = 0; hdmi_slot < 8; hdmi_slot++) {
	for (hdmi_slot = 0; hdmi_slot < 8; hdmi_slot++) {
		int err;
		int err;


		err = spec->chmap.ops.pin_set_slot_channel(&codec->core,
		err = chmap->ops.pin_set_slot_channel(chmap->hdac,
				pin_nid, hdmi_slot, assignments[hdmi_slot]);
				pin_nid, hdmi_slot, assignments[hdmi_slot]);
		if (err)
		if (err)
			return -EINVAL;
			return -EINVAL;
@@ -956,20 +953,20 @@ static void hdmi_setup_fake_chmap(unsigned char *map, int ca)
	}
	}
}
}


static void hdmi_setup_channel_mapping(struct hda_codec *codec,
static void hdmi_setup_channel_mapping(struct hdac_chmap *chmap,
				       hda_nid_t pin_nid, bool non_pcm, int ca,
				       hda_nid_t pin_nid, bool non_pcm, int ca,
				       int channels, unsigned char *map,
				       int channels, unsigned char *map,
				       bool chmap_set)
				       bool chmap_set)
{
{
	if (!non_pcm && chmap_set) {
	if (!non_pcm && chmap_set) {
		hdmi_manual_setup_channel_mapping(codec, pin_nid,
		hdmi_manual_setup_channel_mapping(chmap, pin_nid,
						  channels, map, ca);
						  channels, map, ca);
	} else {
	} else {
		hdmi_std_setup_channel_mapping(codec, pin_nid, non_pcm, ca);
		hdmi_std_setup_channel_mapping(chmap, pin_nid, non_pcm, ca);
		hdmi_setup_fake_chmap(map, ca);
		hdmi_setup_fake_chmap(map, ca);
	}
	}


	hdmi_debug_channel_mapping(codec, pin_nid);
	hdmi_debug_channel_mapping(chmap, pin_nid);
}
}


/*
/*
@@ -1142,6 +1139,35 @@ static void hdmi_pin_setup_infoframe(struct hda_codec *codec,
	}
	}
}
}


static int hdmi_get_active_channels(int ca)
{
	int ordered_ca = get_channel_allocation_order(ca);

	return channel_allocations[ordered_ca].channels;
}

static struct hdac_cea_channel_speaker_allocation *hdmi_get_ch_alloc_from_ca(int ca)
{
	return &channel_allocations[get_channel_allocation_order(ca)];
}

static int hdmi_channel_allocation(struct hdac_device *hdac, int spk_alloc,
		int channels, bool chmap_set, bool non_pcm, unsigned char *map)
{
	int ca;

	if (!non_pcm && chmap_set)
		ca = hdmi_manual_channel_allocation(channels, map);
	else
		ca = hdmi_channel_allocation_spk_alloc_blk(hdac,
					spk_alloc, channels);

	if (ca < 0)
		ca = 0;

	return ca;
}

static void hdmi_setup_audio_infoframe(struct hda_codec *codec,
static void hdmi_setup_audio_infoframe(struct hda_codec *codec,
				       struct hdmi_spec_per_pin *per_pin,
				       struct hdmi_spec_per_pin *per_pin,
				       bool non_pcm)
				       bool non_pcm)
@@ -1152,7 +1178,7 @@ static void hdmi_setup_audio_infoframe(struct hda_codec *codec,
	int channels = per_pin->channels;
	int channels = per_pin->channels;
	int active_channels;
	int active_channels;
	struct hdmi_eld *eld;
	struct hdmi_eld *eld;
	int ca, ordered_ca;
	int ca;


	if (!channels)
	if (!channels)
		return;
		return;
@@ -1164,15 +1190,11 @@ static void hdmi_setup_audio_infoframe(struct hda_codec *codec,


	eld = &per_pin->sink_eld;
	eld = &per_pin->sink_eld;


	if (!non_pcm && per_pin->chmap_set)
	ca = hdmi_channel_allocation(&codec->core,
		ca = hdmi_manual_channel_allocation(channels, per_pin->chmap);
			eld->info.spk_alloc, channels,
	else
			per_pin->chmap_set, non_pcm, per_pin->chmap);
		ca = hdmi_channel_allocation(codec, eld, channels);
	if (ca < 0)
		ca = 0;


	ordered_ca = get_channel_allocation_order(ca);
	active_channels = hdmi_get_active_channels(ca);
	active_channels = channel_allocations[ordered_ca].channels;


	chmap->ops.set_channel_count(&codec->core, per_pin->cvt_nid,
	chmap->ops.set_channel_count(&codec->core, per_pin->cvt_nid,
						active_channels);
						active_channels);
@@ -1181,9 +1203,9 @@ static void hdmi_setup_audio_infoframe(struct hda_codec *codec,
	 * always configure channel mapping, it may have been changed by the
	 * always configure channel mapping, it may have been changed by the
	 * user in the meantime
	 * user in the meantime
	 */
	 */
	hdmi_setup_channel_mapping(codec, pin_nid, non_pcm, ca,
	hdmi_setup_channel_mapping(&spec->chmap,
				   channels, per_pin->chmap,
				pin_nid, non_pcm, ca, channels,
				   per_pin->chmap_set);
				per_pin->chmap, per_pin->chmap_set);


	spec->ops.pin_setup_infoframe(codec, pin_nid, ca, active_channels,
	spec->ops.pin_setup_infoframe(codec, pin_nid, ca, active_channels,
				      eld->info.conn_type);
				      eld->info.conn_type);
@@ -2336,7 +2358,7 @@ static int hdmi_chmap_cea_alloc_validate_get_type(struct hdac_chmap *chmap,
	return SNDRV_CTL_TLVT_CHMAP_VAR;
	return SNDRV_CTL_TLVT_CHMAP_VAR;
}
}


static void hdmi_cea_alloc_to_tlv_chmap(
static void hdmi_cea_alloc_to_tlv_chmap(struct hdac_chmap *hchmap,
		struct hdac_cea_channel_speaker_allocation *cap,
		struct hdac_cea_channel_speaker_allocation *cap,
		unsigned int *chmap, int channels)
		unsigned int *chmap, int channels)
{
{
@@ -2430,7 +2452,8 @@ static int hdmi_chmap_ctl_tlv(struct snd_kcontrol *kcontrol, int op_flag,
				return -ENOMEM;
				return -ENOMEM;
			size -= chs_bytes;
			size -= chs_bytes;
			count += chs_bytes;
			count += chs_bytes;
			chmap->ops.cea_alloc_to_tlv_chmap(cap, tlv_chmap, chs);
			chmap->ops.cea_alloc_to_tlv_chmap(chmap, cap,
						tlv_chmap, chs);
			if (copy_to_user(dst, tlv_chmap, chs_bytes))
			if (copy_to_user(dst, tlv_chmap, chs_bytes))
				return -EFAULT;
				return -EFAULT;
			dst += chs;
			dst += chs;
@@ -2501,7 +2524,8 @@ static int hdmi_chmap_ctl_put(struct snd_kcontrol *kcontrol,
	if (ca < 0)
	if (ca < 0)
		return -EINVAL;
		return -EINVAL;
	if (hchmap->ops.chmap_validate) {
	if (hchmap->ops.chmap_validate) {
		err = hchmap->ops.chmap_validate(ca, ARRAY_SIZE(chmap), chmap);
		err = hchmap->ops.chmap_validate(hchmap, ca,
				ARRAY_SIZE(chmap), chmap);
		if (err)
		if (err)
			return err;
			return err;
	}
	}
@@ -3499,7 +3523,8 @@ static int nvhdmi_chmap_cea_alloc_validate_get_type(struct hdac_chmap *chmap,
				chmap, cap, channels);
				chmap, cap, channels);
}
}


static int nvhdmi_chmap_validate(int ca, int chs, unsigned char *map)
static int nvhdmi_chmap_validate(struct hdac_chmap *chmap,
		int ca, int chs, unsigned char *map)
{
{
	if (ca == 0x00 && (map[0] != SNDRV_CHMAP_FL || map[1] != SNDRV_CHMAP_FR))
	if (ca == 0x00 && (map[0] != SNDRV_CHMAP_FL || map[1] != SNDRV_CHMAP_FR))
		return -EINVAL;
		return -EINVAL;
@@ -3769,14 +3794,15 @@ static int atihdmi_paired_swap_fc_lfe(int pos)
	return pos;
	return pos;
}
}


static int atihdmi_paired_chmap_validate(int ca, int chs, unsigned char *map)
static int atihdmi_paired_chmap_validate(struct hdac_chmap *chmap,
			int ca, int chs, unsigned char *map)
{
{
	struct hdac_cea_channel_speaker_allocation *cap;
	struct hdac_cea_channel_speaker_allocation *cap;
	int i, j;
	int i, j;


	/* check that only channel pairs need to be remapped on old pre-rev3 ATI/AMD */
	/* check that only channel pairs need to be remapped on old pre-rev3 ATI/AMD */


	cap = &channel_allocations[get_channel_allocation_order(ca)];
	cap = hdmi_get_ch_alloc_from_ca(ca);
	for (i = 0; i < chs; ++i) {
	for (i = 0; i < chs; ++i) {
		int mask = to_spk_mask(map[i]);
		int mask = to_spk_mask(map[i]);
		bool ok = false;
		bool ok = false;
@@ -3912,7 +3938,7 @@ static int atihdmi_paired_chmap_cea_alloc_validate_get_type(
	return SNDRV_CTL_TLVT_CHMAP_PAIRED;
	return SNDRV_CTL_TLVT_CHMAP_PAIRED;
}
}


static void atihdmi_paired_cea_alloc_to_tlv_chmap(
static void atihdmi_paired_cea_alloc_to_tlv_chmap(struct hdac_chmap *hchmap,
		struct hdac_cea_channel_speaker_allocation *cap,
		struct hdac_cea_channel_speaker_allocation *cap,
		unsigned int *chmap, int channels)
		unsigned int *chmap, int channels)
{
{