ALSA: hda - hdmi operate spdif based on pcm

Currently, the driver operates the spdif based on pin.
This is ok for the current driver as pcm is statically
bound to the pin.

However, if the driver uses dynamically pcm assignment,
this will cause confusion for user space.

The patch changes spdif operation from pin based to pcm based.

Signed-off-by: Libin Yang <libin.yang@linux.intel.com>
Signed-off-by: Takashi Iwai <tiwai@suse.de>
This commit is contained in:
Libin Yang 2015-12-16 13:42:43 +08:00 committed by Takashi Iwai
parent 42b2987079
commit 2bf3c85a5b

View File

@ -140,6 +140,7 @@ struct hdmi_spec {
struct snd_array pins; /* struct hdmi_spec_per_pin */
struct hda_pcm *pcm_rec[16];
struct mutex pcm_lock;
int pcm_used; /* counter of pcm_rec[] */
unsigned int channels_max; /* max over all cvts */
struct hdmi_eld temp_eld;
@ -387,6 +388,20 @@ static int pin_nid_to_pin_index(struct hda_codec *codec, hda_nid_t pin_nid)
return -EINVAL;
}
static int hinfo_to_pcm_index(struct hda_codec *codec,
struct hda_pcm_stream *hinfo)
{
struct hdmi_spec *spec = codec->spec;
int pcm_idx;
for (pcm_idx = 0; pcm_idx < spec->pcm_used; pcm_idx++)
if (get_pcm_rec(spec, pcm_idx)->stream == hinfo)
return pcm_idx;
codec_warn(codec, "HDMI: hinfo %p not registered\n", hinfo);
return -EINVAL;
}
static int hinfo_to_pin_index(struct hda_codec *codec,
struct hda_pcm_stream *hinfo)
{
@ -1548,13 +1563,17 @@ static int hdmi_pcm_open(struct hda_pcm_stream *hinfo,
{
struct hdmi_spec *spec = codec->spec;
struct snd_pcm_runtime *runtime = substream->runtime;
int pin_idx, cvt_idx, mux_idx = 0;
int pin_idx, cvt_idx, pcm_idx, mux_idx = 0;
struct hdmi_spec_per_pin *per_pin;
struct hdmi_eld *eld;
struct hdmi_spec_per_cvt *per_cvt = NULL;
int err;
/* Validate hinfo */
pcm_idx = hinfo_to_pcm_index(codec, hinfo);
if (pcm_idx < 0)
return -EINVAL;
mutex_lock(&spec->pcm_lock);
pin_idx = hinfo_to_pin_index(codec, hinfo);
if (!spec->dyn_pcm_assign) {
@ -1596,7 +1615,7 @@ static int hdmi_pcm_open(struct hda_pcm_stream *hinfo,
if (is_haswell_plus(codec) || is_valleyview_plus(codec))
intel_not_share_assigned_cvt(codec, per_pin->pin_nid, mux_idx);
snd_hda_spdif_ctls_assign(codec, pin_idx, per_cvt->cvt_nid);
snd_hda_spdif_ctls_assign(codec, pcm_idx, per_cvt->cvt_nid);
/* Initially set the converter's capabilities */
hinfo->channels_min = per_cvt->channels_min;
@ -1613,7 +1632,7 @@ static int hdmi_pcm_open(struct hda_pcm_stream *hinfo,
!hinfo->rates || !hinfo->formats) {
per_cvt->assigned = 0;
hinfo->nid = 0;
snd_hda_spdif_ctls_unassign(codec, pin_idx);
snd_hda_spdif_ctls_unassign(codec, pcm_idx);
mutex_unlock(&spec->pcm_lock);
return -ENODEV;
}
@ -2043,12 +2062,15 @@ static int hdmi_pcm_close(struct hda_pcm_stream *hinfo,
struct snd_pcm_substream *substream)
{
struct hdmi_spec *spec = codec->spec;
int cvt_idx, pin_idx;
int cvt_idx, pin_idx, pcm_idx;
struct hdmi_spec_per_cvt *per_cvt;
struct hdmi_spec_per_pin *per_pin;
int pinctl;
if (hinfo->nid) {
pcm_idx = hinfo_to_pcm_index(codec, hinfo);
if (snd_BUG_ON(pcm_idx < 0))
return -EINVAL;
cvt_idx = cvt_nid_to_cvt_index(codec, hinfo->nid);
if (snd_BUG_ON(cvt_idx < 0))
return -EINVAL;
@ -2079,7 +2101,7 @@ static int hdmi_pcm_close(struct hda_pcm_stream *hinfo,
pinctl & ~PIN_OUT);
}
snd_hda_spdif_ctls_unassign(codec, pin_idx);
snd_hda_spdif_ctls_unassign(codec, pcm_idx);
mutex_lock(&per_pin->lock);
per_pin->chmap_set = false;
@ -2277,6 +2299,7 @@ static int generic_hdmi_build_pcms(struct hda_codec *codec)
per_pin->pcm = info;
}
spec->pcm_rec[pin_idx] = info;
spec->pcm_used++;
info->pcm_type = HDA_PCM_TYPE_HDMI;
info->own_chmap = true;
@ -2353,6 +2376,7 @@ static int generic_hdmi_build_controls(struct hda_codec *codec)
HDA_PCM_TYPE_HDMI);
if (err < 0)
return err;
/* pin number is the same with pcm number so far */
snd_hda_spdif_ctls_unassign(codec, pin_idx);
/* add control for ELD Bytes */