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: Subhransu S. Prusty <subhransu.s.prusty@intel.com>
Signed-off-by: Vinod Koul <vinod.koul@intel.com>
Signed-off-by: Takashi Iwai <tiwai@suse.de>
This commit is contained in:
Subhransu S. Prusty 2016-03-04 19:59:50 +05:30 committed by Takashi Iwai
parent 739ffee97e
commit 828cb4edd8
2 changed files with 74 additions and 44 deletions

View File

@ -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);

View File

@ -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)
{ {