Commit e3245cdd authored by Takashi Iwai's avatar Takashi Iwai

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: default avatarTakashi Iwai <tiwai@suse.de>
parent 61d648fb
...@@ -2864,12 +2864,15 @@ static int snd_hda_spdif_default_get(struct snd_kcontrol *kcontrol, ...@@ -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, ...@@ -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, ...@@ -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, ...@@ -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, ...@@ -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); ...@@ -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); ...@@ -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, ...@@ -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, ...@@ -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;
......
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