ALSA: hda - Protect SPDIF-related stuff via spdif_mutex
Add the missing mutex protection or move into the protected part for SPDIF access codes for codecs. Signed-off-by: Takashi Iwai <tiwai@suse.de>
This commit is contained in:
parent
61d648fb47
commit
e3245cddcf
|
@ -2864,12 +2864,15 @@ static int snd_hda_spdif_default_get(struct snd_kcontrol *kcontrol,
|
||||||
{
|
{
|
||||||
struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
|
struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
|
||||||
int idx = kcontrol->private_value;
|
int idx = kcontrol->private_value;
|
||||||
struct hda_spdif_out *spdif = snd_array_elem(&codec->spdif_out, idx);
|
struct hda_spdif_out *spdif;
|
||||||
|
|
||||||
|
mutex_lock(&codec->spdif_mutex);
|
||||||
|
spdif = snd_array_elem(&codec->spdif_out, idx);
|
||||||
ucontrol->value.iec958.status[0] = spdif->status & 0xff;
|
ucontrol->value.iec958.status[0] = spdif->status & 0xff;
|
||||||
ucontrol->value.iec958.status[1] = (spdif->status >> 8) & 0xff;
|
ucontrol->value.iec958.status[1] = (spdif->status >> 8) & 0xff;
|
||||||
ucontrol->value.iec958.status[2] = (spdif->status >> 16) & 0xff;
|
ucontrol->value.iec958.status[2] = (spdif->status >> 16) & 0xff;
|
||||||
ucontrol->value.iec958.status[3] = (spdif->status >> 24) & 0xff;
|
ucontrol->value.iec958.status[3] = (spdif->status >> 24) & 0xff;
|
||||||
|
mutex_unlock(&codec->spdif_mutex);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
@ -2955,12 +2958,14 @@ static int snd_hda_spdif_default_put(struct snd_kcontrol *kcontrol,
|
||||||
{
|
{
|
||||||
struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
|
struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
|
||||||
int idx = kcontrol->private_value;
|
int idx = kcontrol->private_value;
|
||||||
struct hda_spdif_out *spdif = snd_array_elem(&codec->spdif_out, idx);
|
struct hda_spdif_out *spdif;
|
||||||
hda_nid_t nid = spdif->nid;
|
hda_nid_t nid;
|
||||||
unsigned short val;
|
unsigned short val;
|
||||||
int change;
|
int change;
|
||||||
|
|
||||||
mutex_lock(&codec->spdif_mutex);
|
mutex_lock(&codec->spdif_mutex);
|
||||||
|
spdif = snd_array_elem(&codec->spdif_out, idx);
|
||||||
|
nid = spdif->nid;
|
||||||
spdif->status = ucontrol->value.iec958.status[0] |
|
spdif->status = ucontrol->value.iec958.status[0] |
|
||||||
((unsigned int)ucontrol->value.iec958.status[1] << 8) |
|
((unsigned int)ucontrol->value.iec958.status[1] << 8) |
|
||||||
((unsigned int)ucontrol->value.iec958.status[2] << 16) |
|
((unsigned int)ucontrol->value.iec958.status[2] << 16) |
|
||||||
|
@ -2982,9 +2987,12 @@ static int snd_hda_spdif_out_switch_get(struct snd_kcontrol *kcontrol,
|
||||||
{
|
{
|
||||||
struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
|
struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
|
||||||
int idx = kcontrol->private_value;
|
int idx = kcontrol->private_value;
|
||||||
struct hda_spdif_out *spdif = snd_array_elem(&codec->spdif_out, idx);
|
struct hda_spdif_out *spdif;
|
||||||
|
|
||||||
|
mutex_lock(&codec->spdif_mutex);
|
||||||
|
spdif = snd_array_elem(&codec->spdif_out, idx);
|
||||||
ucontrol->value.integer.value[0] = spdif->ctls & AC_DIG1_ENABLE;
|
ucontrol->value.integer.value[0] = spdif->ctls & AC_DIG1_ENABLE;
|
||||||
|
mutex_unlock(&codec->spdif_mutex);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -3004,12 +3012,14 @@ static int snd_hda_spdif_out_switch_put(struct snd_kcontrol *kcontrol,
|
||||||
{
|
{
|
||||||
struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
|
struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
|
||||||
int idx = kcontrol->private_value;
|
int idx = kcontrol->private_value;
|
||||||
struct hda_spdif_out *spdif = snd_array_elem(&codec->spdif_out, idx);
|
struct hda_spdif_out *spdif;
|
||||||
hda_nid_t nid = spdif->nid;
|
hda_nid_t nid;
|
||||||
unsigned short val;
|
unsigned short val;
|
||||||
int change;
|
int change;
|
||||||
|
|
||||||
mutex_lock(&codec->spdif_mutex);
|
mutex_lock(&codec->spdif_mutex);
|
||||||
|
spdif = snd_array_elem(&codec->spdif_out, idx);
|
||||||
|
nid = spdif->nid;
|
||||||
val = spdif->ctls & ~AC_DIG1_ENABLE;
|
val = spdif->ctls & ~AC_DIG1_ENABLE;
|
||||||
if (ucontrol->value.integer.value[0])
|
if (ucontrol->value.integer.value[0])
|
||||||
val |= AC_DIG1_ENABLE;
|
val |= AC_DIG1_ENABLE;
|
||||||
|
@ -3097,6 +3107,9 @@ int snd_hda_create_spdif_out_ctls(struct hda_codec *codec,
|
||||||
}
|
}
|
||||||
EXPORT_SYMBOL_HDA(snd_hda_create_spdif_out_ctls);
|
EXPORT_SYMBOL_HDA(snd_hda_create_spdif_out_ctls);
|
||||||
|
|
||||||
|
/* get the hda_spdif_out entry from the given NID
|
||||||
|
* call within spdif_mutex lock
|
||||||
|
*/
|
||||||
struct hda_spdif_out *snd_hda_spdif_out_of_nid(struct hda_codec *codec,
|
struct hda_spdif_out *snd_hda_spdif_out_of_nid(struct hda_codec *codec,
|
||||||
hda_nid_t nid)
|
hda_nid_t nid)
|
||||||
{
|
{
|
||||||
|
@ -3113,9 +3126,10 @@ EXPORT_SYMBOL_HDA(snd_hda_spdif_out_of_nid);
|
||||||
|
|
||||||
void snd_hda_spdif_ctls_unassign(struct hda_codec *codec, int idx)
|
void snd_hda_spdif_ctls_unassign(struct hda_codec *codec, int idx)
|
||||||
{
|
{
|
||||||
struct hda_spdif_out *spdif = snd_array_elem(&codec->spdif_out, idx);
|
struct hda_spdif_out *spdif;
|
||||||
|
|
||||||
mutex_lock(&codec->spdif_mutex);
|
mutex_lock(&codec->spdif_mutex);
|
||||||
|
spdif = snd_array_elem(&codec->spdif_out, idx);
|
||||||
spdif->nid = (u16)-1;
|
spdif->nid = (u16)-1;
|
||||||
mutex_unlock(&codec->spdif_mutex);
|
mutex_unlock(&codec->spdif_mutex);
|
||||||
}
|
}
|
||||||
|
@ -3123,10 +3137,11 @@ EXPORT_SYMBOL_HDA(snd_hda_spdif_ctls_unassign);
|
||||||
|
|
||||||
void snd_hda_spdif_ctls_assign(struct hda_codec *codec, int idx, hda_nid_t nid)
|
void snd_hda_spdif_ctls_assign(struct hda_codec *codec, int idx, hda_nid_t nid)
|
||||||
{
|
{
|
||||||
struct hda_spdif_out *spdif = snd_array_elem(&codec->spdif_out, idx);
|
struct hda_spdif_out *spdif;
|
||||||
unsigned short val;
|
unsigned short val;
|
||||||
|
|
||||||
mutex_lock(&codec->spdif_mutex);
|
mutex_lock(&codec->spdif_mutex);
|
||||||
|
spdif = snd_array_elem(&codec->spdif_out, idx);
|
||||||
if (spdif->nid != nid) {
|
if (spdif->nid != nid) {
|
||||||
spdif->nid = nid;
|
spdif->nid = nid;
|
||||||
val = spdif->ctls;
|
val = spdif->ctls;
|
||||||
|
@ -4747,11 +4762,11 @@ int snd_hda_multi_out_analog_prepare(struct hda_codec *codec,
|
||||||
{
|
{
|
||||||
const hda_nid_t *nids = mout->dac_nids;
|
const hda_nid_t *nids = mout->dac_nids;
|
||||||
int chs = substream->runtime->channels;
|
int chs = substream->runtime->channels;
|
||||||
struct hda_spdif_out *spdif =
|
struct hda_spdif_out *spdif;
|
||||||
snd_hda_spdif_out_of_nid(codec, mout->dig_out_nid);
|
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
mutex_lock(&codec->spdif_mutex);
|
mutex_lock(&codec->spdif_mutex);
|
||||||
|
spdif = snd_hda_spdif_out_of_nid(codec, mout->dig_out_nid);
|
||||||
if (mout->dig_out_nid && mout->share_spdif &&
|
if (mout->dig_out_nid && mout->share_spdif &&
|
||||||
mout->dig_out_used != HDA_DIG_EXCLUSIVE) {
|
mout->dig_out_used != HDA_DIG_EXCLUSIVE) {
|
||||||
if (chs == 2 &&
|
if (chs == 2 &&
|
||||||
|
|
|
@ -1592,10 +1592,10 @@ static int nvhdmi_8ch_7x_pcm_prepare(struct hda_pcm_stream *hinfo,
|
||||||
unsigned int dataDCC2, channel_id;
|
unsigned int dataDCC2, channel_id;
|
||||||
int i;
|
int i;
|
||||||
struct hdmi_spec *spec = codec->spec;
|
struct hdmi_spec *spec = codec->spec;
|
||||||
struct hda_spdif_out *spdif =
|
struct hda_spdif_out *spdif;
|
||||||
snd_hda_spdif_out_of_nid(codec, spec->cvts[0].cvt_nid);
|
|
||||||
|
|
||||||
mutex_lock(&codec->spdif_mutex);
|
mutex_lock(&codec->spdif_mutex);
|
||||||
|
spdif = snd_hda_spdif_out_of_nid(codec, spec->cvts[0].cvt_nid);
|
||||||
|
|
||||||
chs = substream->runtime->channels;
|
chs = substream->runtime->channels;
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue