Commit 2bf3c85a authored by Libin Yang's avatar Libin Yang Committed by Takashi Iwai

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: default avatarLibin Yang <libin.yang@linux.intel.com>
Signed-off-by: default avatarTakashi Iwai <tiwai@suse.de>
parent 42b29870
...@@ -140,6 +140,7 @@ struct hdmi_spec { ...@@ -140,6 +140,7 @@ struct hdmi_spec {
struct snd_array pins; /* struct hdmi_spec_per_pin */ struct snd_array pins; /* struct hdmi_spec_per_pin */
struct hda_pcm *pcm_rec[16]; struct hda_pcm *pcm_rec[16];
struct mutex pcm_lock; struct mutex pcm_lock;
int pcm_used; /* counter of pcm_rec[] */
unsigned int channels_max; /* max over all cvts */ unsigned int channels_max; /* max over all cvts */
struct hdmi_eld temp_eld; 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) ...@@ -387,6 +388,20 @@ static int pin_nid_to_pin_index(struct hda_codec *codec, hda_nid_t pin_nid)
return -EINVAL; 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, static int hinfo_to_pin_index(struct hda_codec *codec,
struct hda_pcm_stream *hinfo) struct hda_pcm_stream *hinfo)
{ {
...@@ -1548,13 +1563,17 @@ static int hdmi_pcm_open(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 hdmi_spec *spec = codec->spec;
struct snd_pcm_runtime *runtime = substream->runtime; 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_spec_per_pin *per_pin;
struct hdmi_eld *eld; struct hdmi_eld *eld;
struct hdmi_spec_per_cvt *per_cvt = NULL; struct hdmi_spec_per_cvt *per_cvt = NULL;
int err; int err;
/* Validate hinfo */ /* Validate hinfo */
pcm_idx = hinfo_to_pcm_index(codec, hinfo);
if (pcm_idx < 0)
return -EINVAL;
mutex_lock(&spec->pcm_lock); mutex_lock(&spec->pcm_lock);
pin_idx = hinfo_to_pin_index(codec, hinfo); pin_idx = hinfo_to_pin_index(codec, hinfo);
if (!spec->dyn_pcm_assign) { if (!spec->dyn_pcm_assign) {
...@@ -1596,7 +1615,7 @@ static int hdmi_pcm_open(struct hda_pcm_stream *hinfo, ...@@ -1596,7 +1615,7 @@ static int hdmi_pcm_open(struct hda_pcm_stream *hinfo,
if (is_haswell_plus(codec) || is_valleyview_plus(codec)) if (is_haswell_plus(codec) || is_valleyview_plus(codec))
intel_not_share_assigned_cvt(codec, per_pin->pin_nid, mux_idx); 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 */ /* Initially set the converter's capabilities */
hinfo->channels_min = per_cvt->channels_min; hinfo->channels_min = per_cvt->channels_min;
...@@ -1613,7 +1632,7 @@ static int hdmi_pcm_open(struct hda_pcm_stream *hinfo, ...@@ -1613,7 +1632,7 @@ static int hdmi_pcm_open(struct hda_pcm_stream *hinfo,
!hinfo->rates || !hinfo->formats) { !hinfo->rates || !hinfo->formats) {
per_cvt->assigned = 0; per_cvt->assigned = 0;
hinfo->nid = 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); mutex_unlock(&spec->pcm_lock);
return -ENODEV; return -ENODEV;
} }
...@@ -2043,12 +2062,15 @@ static int hdmi_pcm_close(struct hda_pcm_stream *hinfo, ...@@ -2043,12 +2062,15 @@ static int hdmi_pcm_close(struct hda_pcm_stream *hinfo,
struct snd_pcm_substream *substream) struct snd_pcm_substream *substream)
{ {
struct hdmi_spec *spec = codec->spec; 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_cvt *per_cvt;
struct hdmi_spec_per_pin *per_pin; struct hdmi_spec_per_pin *per_pin;
int pinctl; int pinctl;
if (hinfo->nid) { 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); cvt_idx = cvt_nid_to_cvt_index(codec, hinfo->nid);
if (snd_BUG_ON(cvt_idx < 0)) if (snd_BUG_ON(cvt_idx < 0))
return -EINVAL; return -EINVAL;
...@@ -2079,7 +2101,7 @@ static int hdmi_pcm_close(struct hda_pcm_stream *hinfo, ...@@ -2079,7 +2101,7 @@ static int hdmi_pcm_close(struct hda_pcm_stream *hinfo,
pinctl & ~PIN_OUT); pinctl & ~PIN_OUT);
} }
snd_hda_spdif_ctls_unassign(codec, pin_idx); snd_hda_spdif_ctls_unassign(codec, pcm_idx);
mutex_lock(&per_pin->lock); mutex_lock(&per_pin->lock);
per_pin->chmap_set = false; per_pin->chmap_set = false;
...@@ -2277,6 +2299,7 @@ static int generic_hdmi_build_pcms(struct hda_codec *codec) ...@@ -2277,6 +2299,7 @@ static int generic_hdmi_build_pcms(struct hda_codec *codec)
per_pin->pcm = info; per_pin->pcm = info;
} }
spec->pcm_rec[pin_idx] = info; spec->pcm_rec[pin_idx] = info;
spec->pcm_used++;
info->pcm_type = HDA_PCM_TYPE_HDMI; info->pcm_type = HDA_PCM_TYPE_HDMI;
info->own_chmap = true; info->own_chmap = true;
...@@ -2353,6 +2376,7 @@ static int generic_hdmi_build_controls(struct hda_codec *codec) ...@@ -2353,6 +2376,7 @@ static int generic_hdmi_build_controls(struct hda_codec *codec)
HDA_PCM_TYPE_HDMI); HDA_PCM_TYPE_HDMI);
if (err < 0) if (err < 0)
return err; return err;
/* pin number is the same with pcm number so far */
snd_hda_spdif_ctls_unassign(codec, pin_idx); snd_hda_spdif_ctls_unassign(codec, pin_idx);
/* add control for ELD Bytes */ /* add control for ELD Bytes */
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment