mirror of
https://github.com/Fishwaldo/linux-bl808.git
synced 2025-04-13 17:55:14 +00:00
ALSA: hda - hdmi eld control created based on pcm
eld control is created based on pcm now. When monitor is connected, eld control will be bound to pin automatically. Signed-off-by: Libin Yang <libin.yang@linux.intel.com> Signed-off-by: Takashi Iwai <tiwai@suse.de>
This commit is contained in:
parent
fe0d128c57
commit
fb087eaaef
1 changed files with 48 additions and 26 deletions
|
@ -86,7 +86,6 @@ struct hdmi_spec_per_pin {
|
||||||
struct hdmi_eld sink_eld;
|
struct hdmi_eld sink_eld;
|
||||||
struct mutex lock;
|
struct mutex lock;
|
||||||
struct delayed_work work;
|
struct delayed_work work;
|
||||||
struct snd_kcontrol *eld_ctl;
|
|
||||||
struct hdmi_pcm *pcm; /* pointer to spec->pcm_rec[n] dynamically*/
|
struct hdmi_pcm *pcm; /* pointer to spec->pcm_rec[n] dynamically*/
|
||||||
int pcm_idx; /* which pcm is attached. -1 means no pcm is attached */
|
int pcm_idx; /* which pcm is attached. -1 means no pcm is attached */
|
||||||
int repoll_count;
|
int repoll_count;
|
||||||
|
@ -136,6 +135,7 @@ struct hdmi_ops {
|
||||||
struct hdmi_pcm {
|
struct hdmi_pcm {
|
||||||
struct hda_pcm *pcm;
|
struct hda_pcm *pcm;
|
||||||
struct snd_jack *jack;
|
struct snd_jack *jack;
|
||||||
|
struct snd_kcontrol *eld_ctl;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct hdmi_spec {
|
struct hdmi_spec {
|
||||||
|
@ -471,17 +471,22 @@ static int hdmi_eld_ctl_info(struct snd_kcontrol *kcontrol,
|
||||||
struct hdmi_spec *spec = codec->spec;
|
struct hdmi_spec *spec = codec->spec;
|
||||||
struct hdmi_spec_per_pin *per_pin;
|
struct hdmi_spec_per_pin *per_pin;
|
||||||
struct hdmi_eld *eld;
|
struct hdmi_eld *eld;
|
||||||
int pin_idx;
|
int pcm_idx;
|
||||||
|
|
||||||
uinfo->type = SNDRV_CTL_ELEM_TYPE_BYTES;
|
uinfo->type = SNDRV_CTL_ELEM_TYPE_BYTES;
|
||||||
|
|
||||||
pin_idx = kcontrol->private_value;
|
pcm_idx = kcontrol->private_value;
|
||||||
per_pin = get_pin(spec, pin_idx);
|
mutex_lock(&spec->pcm_lock);
|
||||||
|
per_pin = pcm_idx_to_pin(spec, pcm_idx);
|
||||||
|
if (!per_pin) {
|
||||||
|
/* no pin is bound to the pcm */
|
||||||
|
uinfo->count = 0;
|
||||||
|
mutex_unlock(&spec->pcm_lock);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
eld = &per_pin->sink_eld;
|
eld = &per_pin->sink_eld;
|
||||||
|
|
||||||
mutex_lock(&per_pin->lock);
|
|
||||||
uinfo->count = eld->eld_valid ? eld->eld_size : 0;
|
uinfo->count = eld->eld_valid ? eld->eld_size : 0;
|
||||||
mutex_unlock(&per_pin->lock);
|
mutex_unlock(&spec->pcm_lock);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
@ -493,16 +498,23 @@ static int hdmi_eld_ctl_get(struct snd_kcontrol *kcontrol,
|
||||||
struct hdmi_spec *spec = codec->spec;
|
struct hdmi_spec *spec = codec->spec;
|
||||||
struct hdmi_spec_per_pin *per_pin;
|
struct hdmi_spec_per_pin *per_pin;
|
||||||
struct hdmi_eld *eld;
|
struct hdmi_eld *eld;
|
||||||
int pin_idx;
|
int pcm_idx;
|
||||||
|
|
||||||
pin_idx = kcontrol->private_value;
|
pcm_idx = kcontrol->private_value;
|
||||||
per_pin = get_pin(spec, pin_idx);
|
mutex_lock(&spec->pcm_lock);
|
||||||
|
per_pin = pcm_idx_to_pin(spec, pcm_idx);
|
||||||
|
if (!per_pin) {
|
||||||
|
/* no pin is bound to the pcm */
|
||||||
|
memset(ucontrol->value.bytes.data, 0,
|
||||||
|
ARRAY_SIZE(ucontrol->value.bytes.data));
|
||||||
|
mutex_unlock(&spec->pcm_lock);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
eld = &per_pin->sink_eld;
|
eld = &per_pin->sink_eld;
|
||||||
|
|
||||||
mutex_lock(&per_pin->lock);
|
|
||||||
if (eld->eld_size > ARRAY_SIZE(ucontrol->value.bytes.data) ||
|
if (eld->eld_size > ARRAY_SIZE(ucontrol->value.bytes.data) ||
|
||||||
eld->eld_size > ELD_MAX_SIZE) {
|
eld->eld_size > ELD_MAX_SIZE) {
|
||||||
mutex_unlock(&per_pin->lock);
|
mutex_unlock(&spec->pcm_lock);
|
||||||
snd_BUG();
|
snd_BUG();
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
}
|
}
|
||||||
|
@ -512,7 +524,7 @@ static int hdmi_eld_ctl_get(struct snd_kcontrol *kcontrol,
|
||||||
if (eld->eld_valid)
|
if (eld->eld_valid)
|
||||||
memcpy(ucontrol->value.bytes.data, eld->eld_buffer,
|
memcpy(ucontrol->value.bytes.data, eld->eld_buffer,
|
||||||
eld->eld_size);
|
eld->eld_size);
|
||||||
mutex_unlock(&per_pin->lock);
|
mutex_unlock(&spec->pcm_lock);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
@ -525,7 +537,7 @@ static struct snd_kcontrol_new eld_bytes_ctl = {
|
||||||
.get = hdmi_eld_ctl_get,
|
.get = hdmi_eld_ctl_get,
|
||||||
};
|
};
|
||||||
|
|
||||||
static int hdmi_create_eld_ctl(struct hda_codec *codec, int pin_idx,
|
static int hdmi_create_eld_ctl(struct hda_codec *codec, int pcm_idx,
|
||||||
int device)
|
int device)
|
||||||
{
|
{
|
||||||
struct snd_kcontrol *kctl;
|
struct snd_kcontrol *kctl;
|
||||||
|
@ -535,14 +547,17 @@ static int hdmi_create_eld_ctl(struct hda_codec *codec, int pin_idx,
|
||||||
kctl = snd_ctl_new1(&eld_bytes_ctl, codec);
|
kctl = snd_ctl_new1(&eld_bytes_ctl, codec);
|
||||||
if (!kctl)
|
if (!kctl)
|
||||||
return -ENOMEM;
|
return -ENOMEM;
|
||||||
kctl->private_value = pin_idx;
|
kctl->private_value = pcm_idx;
|
||||||
kctl->id.device = device;
|
kctl->id.device = device;
|
||||||
|
|
||||||
err = snd_hda_ctl_add(codec, get_pin(spec, pin_idx)->pin_nid, kctl);
|
/* no pin nid is associated with the kctl now
|
||||||
|
* tbd: associate pin nid to eld ctl later
|
||||||
|
*/
|
||||||
|
err = snd_hda_ctl_add(codec, 0, kctl);
|
||||||
if (err < 0)
|
if (err < 0)
|
||||||
return err;
|
return err;
|
||||||
|
|
||||||
get_pin(spec, pin_idx)->eld_ctl = kctl;
|
get_hdmi_pcm(spec, pcm_idx)->eld_ctl = kctl;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1841,7 +1856,10 @@ static void update_eld(struct hda_codec *codec,
|
||||||
struct hdmi_spec *spec = codec->spec;
|
struct hdmi_spec *spec = codec->spec;
|
||||||
bool old_eld_valid = pin_eld->eld_valid;
|
bool old_eld_valid = pin_eld->eld_valid;
|
||||||
bool eld_changed;
|
bool eld_changed;
|
||||||
|
int pcm_idx = -1;
|
||||||
|
|
||||||
|
/* for monitor disconnection, save pcm_idx firstly */
|
||||||
|
pcm_idx = per_pin->pcm_idx;
|
||||||
if (spec->dyn_pcm_assign) {
|
if (spec->dyn_pcm_assign) {
|
||||||
if (eld->eld_valid) {
|
if (eld->eld_valid) {
|
||||||
hdmi_attach_hda_pcm(spec, per_pin);
|
hdmi_attach_hda_pcm(spec, per_pin);
|
||||||
|
@ -1851,6 +1869,11 @@ static void update_eld(struct hda_codec *codec,
|
||||||
hdmi_detach_hda_pcm(spec, per_pin);
|
hdmi_detach_hda_pcm(spec, per_pin);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
/* if pcm_idx == -1, it means this is in monitor connection event
|
||||||
|
* we can get the correct pcm_idx now.
|
||||||
|
*/
|
||||||
|
if (pcm_idx == -1)
|
||||||
|
pcm_idx = per_pin->pcm_idx;
|
||||||
|
|
||||||
if (eld->eld_valid)
|
if (eld->eld_valid)
|
||||||
snd_hdmi_show_eld(codec, &eld->info);
|
snd_hdmi_show_eld(codec, &eld->info);
|
||||||
|
@ -1884,11 +1907,11 @@ static void update_eld(struct hda_codec *codec,
|
||||||
hdmi_setup_audio_infoframe(codec, per_pin, per_pin->non_pcm);
|
hdmi_setup_audio_infoframe(codec, per_pin, per_pin->non_pcm);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (eld_changed)
|
if (eld_changed && pcm_idx >= 0)
|
||||||
snd_ctl_notify(codec->card,
|
snd_ctl_notify(codec->card,
|
||||||
SNDRV_CTL_EVENT_MASK_VALUE |
|
SNDRV_CTL_EVENT_MASK_VALUE |
|
||||||
SNDRV_CTL_EVENT_MASK_INFO,
|
SNDRV_CTL_EVENT_MASK_INFO,
|
||||||
&per_pin->eld_ctl->id);
|
&get_hdmi_pcm(spec, pcm_idx)->eld_ctl->id);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* update ELD and jack state via HD-audio verbs */
|
/* update ELD and jack state via HD-audio verbs */
|
||||||
|
@ -2629,18 +2652,17 @@ static int generic_hdmi_build_controls(struct hda_codec *codec)
|
||||||
if (err < 0)
|
if (err < 0)
|
||||||
return err;
|
return err;
|
||||||
snd_hda_spdif_ctls_unassign(codec, pcm_idx);
|
snd_hda_spdif_ctls_unassign(codec, pcm_idx);
|
||||||
|
|
||||||
|
/* add control for ELD Bytes */
|
||||||
|
err = hdmi_create_eld_ctl(codec, pcm_idx,
|
||||||
|
get_pcm_rec(spec, pcm_idx)->device);
|
||||||
|
if (err < 0)
|
||||||
|
return err;
|
||||||
}
|
}
|
||||||
|
|
||||||
for (pin_idx = 0; pin_idx < spec->num_pins; pin_idx++) {
|
for (pin_idx = 0; pin_idx < spec->num_pins; pin_idx++) {
|
||||||
struct hdmi_spec_per_pin *per_pin = get_pin(spec, pin_idx);
|
struct hdmi_spec_per_pin *per_pin = get_pin(spec, pin_idx);
|
||||||
|
|
||||||
/* add control for ELD Bytes */
|
|
||||||
err = hdmi_create_eld_ctl(codec, pin_idx,
|
|
||||||
get_pcm_rec(spec, pin_idx)->device);
|
|
||||||
|
|
||||||
if (err < 0)
|
|
||||||
return err;
|
|
||||||
|
|
||||||
hdmi_present_sense(per_pin, 0);
|
hdmi_present_sense(per_pin, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Add table
Reference in a new issue