mirror of
https://github.com/Fishwaldo/linux-bl808.git
synced 2025-05-12 02:06:00 +00:00
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: 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:
parent
67b90cb84b
commit
9b3dc8aa3f
2 changed files with 65 additions and 34 deletions
|
@ -30,6 +30,12 @@ struct hdac_chmap_ops {
|
||||||
|
|
||||||
/* 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)(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 {
|
struct hdac_chmap {
|
||||||
|
|
|
@ -100,8 +100,6 @@ struct hdmi_spec_per_pin {
|
||||||
#endif
|
#endif
|
||||||
};
|
};
|
||||||
|
|
||||||
struct cea_channel_speaker_allocation;
|
|
||||||
|
|
||||||
/* operations used by generic code that can be overridden by patches */
|
/* operations used by generic code that can be overridden by patches */
|
||||||
struct hdmi_ops {
|
struct hdmi_ops {
|
||||||
int (*pin_get_eld)(struct hda_codec *codec, hda_nid_t pin_nid,
|
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_ctl_elem_info *uinfo)
|
||||||
{
|
{
|
||||||
struct snd_pcm_chmap *info = snd_kcontrol_chip(kcontrol);
|
struct snd_pcm_chmap *info = snd_kcontrol_chip(kcontrol);
|
||||||
struct hda_codec *codec = info->private_data;
|
struct hdac_chmap *chmap = info->private_data;
|
||||||
struct hdmi_spec *spec = codec->spec;
|
|
||||||
struct hdac_chmap *chmap = &spec->chmap;
|
|
||||||
|
|
||||||
uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
|
uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
|
||||||
uinfo->count = chmap->channels_max;
|
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);
|
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,
|
static int hdmi_chmap_ctl_tlv(struct snd_kcontrol *kcontrol, int op_flag,
|
||||||
unsigned int size, unsigned int __user *tlv)
|
unsigned int size, unsigned int __user *tlv)
|
||||||
{
|
{
|
||||||
struct snd_pcm_chmap *info = snd_kcontrol_chip(kcontrol);
|
struct snd_pcm_chmap *info = snd_kcontrol_chip(kcontrol);
|
||||||
struct hda_codec *codec = info->private_data;
|
struct hdac_chmap *chmap = info->private_data;
|
||||||
struct hdmi_spec *spec = codec->spec;
|
|
||||||
struct hdac_chmap *chmap = &spec->chmap;
|
|
||||||
unsigned int __user *dst;
|
unsigned int __user *dst;
|
||||||
int chs, count = 0;
|
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_ctl_elem_value *ucontrol)
|
||||||
{
|
{
|
||||||
struct snd_pcm_chmap *info = snd_kcontrol_chip(kcontrol);
|
struct snd_pcm_chmap *info = snd_kcontrol_chip(kcontrol);
|
||||||
struct hda_codec *codec = info->private_data;
|
struct hdac_chmap *chmap = info->private_data;
|
||||||
struct hdmi_spec *spec = codec->spec;
|
|
||||||
struct hdac_chmap *chmap = &spec->chmap;
|
|
||||||
int pcm_idx = kcontrol->private_value;
|
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;
|
int i;
|
||||||
|
|
||||||
if (!per_pin) {
|
memset(pcm_chmap, 0, sizeof(pcm_chmap));
|
||||||
for (i = 0; i < chmap->channels_max; i++)
|
chmap->ops.get_chmap(chmap->hdac, pcm_idx, pcm_chmap);
|
||||||
ucontrol->value.integer.value[i] = 0;
|
|
||||||
return 0;
|
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;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2466,20 +2494,17 @@ static int hdmi_chmap_ctl_put(struct snd_kcontrol *kcontrol,
|
||||||
struct snd_ctl_elem_value *ucontrol)
|
struct snd_ctl_elem_value *ucontrol)
|
||||||
{
|
{
|
||||||
struct snd_pcm_chmap *info = snd_kcontrol_chip(kcontrol);
|
struct snd_pcm_chmap *info = snd_kcontrol_chip(kcontrol);
|
||||||
struct hda_codec *codec = info->private_data;
|
struct hdac_chmap *hchmap = info->private_data;
|
||||||
struct hdmi_spec *spec = codec->spec;
|
|
||||||
struct hdac_chmap *hchmap = &spec->chmap;
|
|
||||||
int pcm_idx = kcontrol->private_value;
|
int pcm_idx = kcontrol->private_value;
|
||||||
struct hdmi_spec_per_pin *per_pin = pcm_idx_to_pin(spec, pcm_idx);
|
|
||||||
unsigned int ctl_idx;
|
unsigned int ctl_idx;
|
||||||
struct snd_pcm_substream *substream;
|
struct snd_pcm_substream *substream;
|
||||||
unsigned char chmap[8];
|
unsigned char chmap[8], per_pin_chmap[8];
|
||||||
int i, err, ca, prepared = 0;
|
int i, err, ca, prepared = 0;
|
||||||
|
|
||||||
/* No monitor is connected in dyn_pcm_assign.
|
/* No monitor is connected in dyn_pcm_assign.
|
||||||
* It's invalid to setup the chmap
|
* It's invalid to setup the chmap
|
||||||
*/
|
*/
|
||||||
if (!per_pin)
|
if (!hchmap->ops.is_pcm_attached(hchmap->hdac, pcm_idx))
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
ctl_idx = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id);
|
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));
|
memset(chmap, 0, sizeof(chmap));
|
||||||
for (i = 0; i < ARRAY_SIZE(chmap); i++)
|
for (i = 0; i < ARRAY_SIZE(chmap); i++)
|
||||||
chmap[i] = ucontrol->value.integer.value[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;
|
return 0;
|
||||||
ca = hdmi_manual_channel_allocation(ARRAY_SIZE(chmap), chmap);
|
ca = hdmi_manual_channel_allocation(ARRAY_SIZE(chmap), chmap);
|
||||||
if (ca < 0)
|
if (ca < 0)
|
||||||
|
@ -2509,12 +2536,8 @@ static int hdmi_chmap_ctl_put(struct snd_kcontrol *kcontrol,
|
||||||
if (err)
|
if (err)
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
mutex_lock(&per_pin->lock);
|
|
||||||
per_pin->chmap_set = true;
|
hchmap->ops.set_chmap(hchmap->hdac, pcm_idx, chmap, prepared);
|
||||||
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);
|
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
@ -2672,7 +2695,7 @@ static int generic_hdmi_build_controls(struct hda_codec *codec)
|
||||||
if (err < 0)
|
if (err < 0)
|
||||||
return err;
|
return err;
|
||||||
/* override handlers */
|
/* override handlers */
|
||||||
chmap->private_data = codec;
|
chmap->private_data = &spec->chmap;
|
||||||
kctl = chmap->kctl;
|
kctl = chmap->kctl;
|
||||||
for (i = 0; i < kctl->count; i++)
|
for (i = 0; i < kctl->count; i++)
|
||||||
kctl->vd[i].access |= SNDRV_CTL_ELEM_ACCESS_WRITE;
|
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 = {
|
static const struct hdac_chmap_ops chmap_ops = {
|
||||||
.chmap_cea_alloc_validate_get_type = hdmi_chmap_cea_alloc_validate_get_type,
|
.chmap_cea_alloc_validate_get_type = hdmi_chmap_cea_alloc_validate_get_type,
|
||||||
.cea_alloc_to_tlv_chmap = hdmi_cea_alloc_to_tlv_chmap,
|
.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,
|
static void intel_haswell_fixup_connect_list(struct hda_codec *codec,
|
||||||
hda_nid_t nid)
|
hda_nid_t nid)
|
||||||
{
|
{
|
||||||
|
|
Loading…
Add table
Reference in a new issue